Whamcloud - gitweb
New files:
authorbraam <braam>
Thu, 21 Oct 1999 18:39:47 +0000 (18:39 +0000)
committerbraam <braam>
Thu, 21 Oct 1999 18:39:47 +0000 (18:39 +0000)
for raid1
for snap shots
OLVM a technical description of the logical volume management
genops generic operations useful to many obd clients

Fixes:
numerous fixes to the file system
several fixes to OBD and obdcontrol

Current state:
does not compile

17 files changed:
lustre/include/linux/obd.h [new file with mode: 0644]
lustre/include/linux/obd_class.h
lustre/include/linux/obd_raid1.h [new file with mode: 0644]
lustre/include/linux/obd_sim.h
lustre/include/linux/obd_snap.h [new file with mode: 0644]
lustre/include/linux/obd_support.h
lustre/include/linux/obdfs.h
lustre/obdclass/class_obd.c
lustre/obdclass/genops.c [new file with mode: 0644]
lustre/obdclass/obdcontrol
lustre/obdclass/setup.sh [new file with mode: 0755]
lustre/obdfs/dir.c
lustre/obdfs/file.c
lustre/obdfs/namei.c
lustre/obdfs/rw.c
lustre/obdfs/super.c
lustre/patches/patch-2.3.21 [new file with mode: 0644]

diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h
new file mode 100644 (file)
index 0000000..03add50
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __OBD_H
+#define __OBD_H
+
+
+struct obd_conn_info {
+       unsigned int conn_id;     /* handle */
+};
+
+struct obd_type {
+       struct list_head typ_chain;
+       struct obd_ops *typ_ops;
+       char *typ_name;
+       int  typ_refcnt;
+};
+
+
+
+
+#endif
index 200e45b..2489e70 100644 (file)
@@ -1,27 +1,27 @@
-#ifndef __LINUX_SIM_OBD_H
-#define __LINUX_SIM_OBD_H
+#ifndef __LINUX_CLASS_OBD_H
+#define __LINUX_CLASS_OBD_H
 
 #include <linux/fs.h>
 #include <linux/ext2_fs.h>
 
+#include <linux/obd.h>
+
 #include <linux/obd_sim.h>
+#include <linux/obd_snap.h>
 /* #include <linux/obd_fc.h> */
+#include <linux/obd_raid1.h>
+
 
 #define OBD_PSDEV_MAJOR 120
 #define MAX_OBD_DEVICES 2
+#define MAX_MULTI 16
+
+typedef unsigned long objid;
+typedef struct inode obdattr;
 
 extern struct obd_device obd_dev[MAX_OBD_DEVICES];
 
-struct obd_conn_info {
-       unsigned int conn_id;     /* handle */
-};
 
-struct obd_type {
-       struct list_head typ_chain;
-       struct obd_ops *typ_ops;
-       char *typ_name;
-       int  typ_refcnt;
-};
 
 #define OBD_ATTACHED 0x1
 #define OBD_SET_UP   0x2
@@ -32,8 +32,16 @@ struct obd_device {
        int obd_minor;
        int obd_flags;
        int obd_refcnt; 
+       int obd_multi_count;
+       struct obd_device *obd_multi_dev[MAX_MULTI];
+       struct obd_conn_info obd_multi_conns[MAX_MULTI];
+       unsigned int obd_gen_last_id;
+       unsigned long obd_gen_prealloc_quota;
+       struct list_head obd_gen_clients;
        union {
                struct sim_obd sim;
+               struct raid1_obd raid1;
+               struct snap_obd snap;
                /* struct fc_obd fc; */
        } u;
 };
@@ -49,18 +57,20 @@ struct obd_ops {
        int (*o_setattr)(unsigned int conn_id, unsigned long id, struct inode *iattr);
        int (*o_getattr)(unsigned int conn_id, unsigned long id, struct inode *iattr);
        int (*o_statfs)(unsigned int conn_id, struct statfs *statfs);
-       int (*o_create)(struct obd_device *, int prealloc_ino, int *er);
+       int (*o_create)(int conn_id, int prealloc_ino, int *er);
        int (*o_destroy)(unsigned int conn_id, unsigned long ino);
        unsigned long (*o_read)(unsigned int conn_id, unsigned long ino, char *buf, unsigned long count, loff_t offset, int *err);
        unsigned long (*o_read2)(unsigned int conn_id, unsigned long ino, char *buf, unsigned long count, loff_t offset, int *err);
        unsigned long (*o_write)(unsigned int conn_id, unsigned long ino, char *buf, unsigned long count, loff_t offset, int *err);
        int (*o_brw)(int rw, int conn, int objectid, struct page *page, int create);
        long (*o_preallocate)(unsigned int conn_id, int req, long inodes[32], int *err);
-       void (*o_cleanup_device)(int dev);
+       int (*o_cleanup_device)(struct obd_device *);
        int  (*o_get_info)(unsigned int conn_id, int keylen, void *key, int *vallen, void **val);
        int  (*o_set_info)(unsigned int conn_id, int keylen, void *key, int vallen, void *val);
 };
 
+#define OBP(dev,op) dev->obd_type->typ_ops->o_ ## op
+
 int obd_register_type(struct obd_ops *ops, char *nm);
 int obd_unregister_type(char *nm);
 
@@ -77,6 +87,19 @@ struct obd_prealloc_inode {
        unsigned long inode;
 };
 
+/* generic operations shared by various OBD types */
+int gen_connect (struct obd_device *obddev, 
+                    struct obd_conn_info * conninfo);
+int gen_disconnect(unsigned int conn_id);
+int gen_multi_setup(struct obd_device *obddev, int len, void *data);
+int gen_multi_cleanup(struct obd_device *obddev);
+int gen_multi_attach(struct obd_device *obddev, int len, void *data);
+struct obd_client *gen_client(int cli_id);
+int gen_multi_cleanup_device(struct obd_device *obddev);
+int gen_cleanup(struct obd_device *obddev);
+
+
+
 /*
  * ioctl commands
  */
@@ -94,10 +117,15 @@ struct oic_prealloc_s {
                     * of succesfully preallocated inodes */
        long inodes[32]; /* actual inode numbers */
 };
-struct oic_attr_s {
+
+struct oic_create_s {
        unsigned int conn_id;
-       unsigned long inode;
+       unsigned long prealloc;
+};
 
+struct oic_attr_s {
+       unsigned int conn_id;
+       unsigned long ino;
        struct iattr iattr;
 };
 struct oic_rw_s {
@@ -115,7 +143,7 @@ struct oic_partition {
 
 #define OBD_IOC_CREATE                 _IOR ('f',  3, long)
 #define OBD_IOC_SETUP_OBDDEV           _IOW ('f',  4, long)
-#define OBD_IOC_CLEANUP_OBDDEV         _IO  ('f',  5      )
+#define OBD_IOC_CLEANUP                _IO  ('f',  5      )
 #define OBD_IOC_DESTROY                _IOW ('f',  6, long)
 #define OBD_IOC_PREALLOCATE            _IOWR('f',  7, long)
 #define OBD_IOC_DEC_USE_COUNT          _IO  ('f',  8      )
@@ -140,4 +168,4 @@ extern void obd_sysctl_init (void);
 extern void obd_sysctl_clean (void);
 
 
-#endif /* __LINUX_SIM_OBD_H */
+#endif /* __LINUX_CLASS_OBD_H */
diff --git a/lustre/include/linux/obd_raid1.h b/lustre/include/linux/obd_raid1.h
new file mode 100644 (file)
index 0000000..cebe311
--- /dev/null
@@ -0,0 +1,98 @@
+#ifndef _OBD_RAID1
+#define _OBD_RAID1
+
+#include <linux/obd_class.h>
+
+#define MAX_RAID1 16
+
+
+struct raid1_obd {
+       unsigned int raid1_count; /* how many replicas */
+       /* devices to replicate on */
+       struct obd_device *raid1_devlist[MAX_RAID1];
+       /* connections we make */
+       struct obd_conn_info raid1_connections[MAX_RAID1];
+       struct list_head raid1_clients;  /* clients we have */
+};
+
+
+/* development definitions */
+extern struct obdfs_sb_info *obd_sbi;
+extern struct file_operations *obd_fso;
+
+/* obd_raid1.c */
+extern struct obd_ops raid1_obd_ops;
+inline long ext2_block_map (struct inode * inode, long block);
+
+/* balloc.c */
+int ext2_new_block (const struct inode * inode, unsigned long goal,
+                   u32 * prealloc_count, u32 * prealloc_block, int * err);
+void ext2_free_blocks (const struct inode * inode, unsigned long block,
+                      unsigned long count);
+unsigned long ext2_count_free_blocks (struct super_block * sb);
+int ext2_group_sparse(int group);
+struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
+                                            unsigned int block_group,
+                                            struct buffer_head ** bh);
+
+/* bitmap.c */
+unsigned long ext2_count_free(struct buffer_head * map, unsigned int numchars);
+
+/* fsync.c */
+extern int obd_sync_file(struct file * file, struct dentry *dentry);
+
+/* ialloc.c */
+extern void ext2_free_inode (struct inode * inode);
+extern struct inode * ext2_new_inode (const struct inode * dir, int mode,
+                                    int * err);
+extern unsigned long ext2_count_free_inodes (struct super_block * sb);
+extern void ext2_check_inodes_bitmap (struct super_block * sb);
+extern int load_inode_bitmap (struct super_block * sb,
+                             unsigned int block_group);
+
+/* inode.c */
+void obd_read_inode (struct inode * inode);
+void obd_write_inode (struct inode * inode);
+void obd_put_inode (struct inode * inode);
+void obd_delete_inode (struct inode * inode);
+void obd_discard_prealloc_blocks (struct inode * inode);
+int obd_sync_inode (struct inode *inode);
+struct buffer_head * obd_bread (struct inode * inode, int block, 
+                                int create, int *err);
+struct buffer_head * obd_getblk (struct inode * inode, long block,
+                                 int create, int * err);
+
+
+/* super.c */
+#define ext2_warning obd_warning
+#undef ext2_error
+#define ext2_error obd_warning
+#define ext2_panic obd_warning
+#ifdef EXT2FS_DEBUG
+#  undef ext2_debug
+#  define ext2_debug(format, a...) CDEBUG(D_EXT2, format, ## a)
+#endif
+
+#define obd_error obd_warning
+#define obd_panic obd_warning
+#define obd_warning(sb, func, format, a...) CDEBUG(D_WARNING, format, ## a)
+
+int obd_remount (struct super_block * sb, int * flags, char * data);
+struct super_block * ext2_read_super (struct super_block * sb, void * data,
+                                     int silent);
+
+/* truncate.c */
+void obd_truncate (struct inode * inode);
+
+/* operations */
+/* dir.c */
+extern struct inode_operations ext2_dir_inode_operations;
+
+/* file.c */
+extern struct file_operations ext2_file_operations;
+extern struct inode_operations ext2_file_inode_operations;
+
+/* super.c */
+extern struct super_operations ext2_sops;
+
+#endif
index 6b56399..b973e0b 100644 (file)
@@ -3,9 +3,6 @@
 
 struct sim_obd {
        struct super_block * sim_sb;
-       unsigned int sim_last_id;
-       unsigned long sim_prealloc_quota;
-       struct list_head sim_clients;
 };
 
 
diff --git a/lustre/include/linux/obd_snap.h b/lustre/include/linux/obd_snap.h
new file mode 100644 (file)
index 0000000..b846fab
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _OBD_SIM
+#define _OBD_SIM
+
+#define OBD_SNAP_MAGIC 0x47224722
+
+#define SNAP_MAX  8 /* must fit in "u" area of struct inode */
+struct snap_obd_data {
+       int snap_dev;             /* which device contains the data */
+       unsigned int snap_no;    /* which snapshot are we accessing */
+       unsigned int snap_count; /* how many snapshots exist */
+       time_t snap_times[SNAP_MAX];
+};
+
+struct snap_obd {
+       unsigned int snap_no;    /* which snapshot are we accessing */
+       unsigned int snap_count; /* how many snapshots exist */
+       time_t snap_times[SNAP_MAX];
+};
+
+struct snap_object_data {
+       int od_magic;
+       /* id of snaps of object; slot 0 has the current data */
+       unsigned long od_ids[SNAP_MAX + 1]; 
+}
+
+
+
+#endif
index 4e2c6e5..57163c5 100644 (file)
@@ -5,6 +5,10 @@
 
 #define SIM_OBD_DEBUG
 
+
+#define MIN(a,b) (((a)<(b)) ? (a): (b))
+#define MAX(a,b) (((a)>(b)) ? (a): (b))
+
 /*
  * Debug code
  */
@@ -53,7 +57,7 @@ extern int obd_print_entry;
 
 #define CMD(cmd) (( cmd == READ ) ? "read" : "write")
 
-#define PDEBUG(page,cmd)       {\
+#define PDEBUG(page,cmd)       {if (page){\
                char *uptodate = (Page_Uptodate(page)) ? "yes" : "no";\
                char *locked = (PageLocked(page)) ? "yes" : "no";\
                int count = page->count.counter;\
@@ -61,9 +65,9 @@ extern int obd_print_entry;
                 long offset = page->offset / PAGE_SIZE;\
                \
                CDEBUG(D_IOCTL, " ** %s, cmd: %s, ino: %ld, off %ld, uptodate: %s, "\
-                      "locked: %s, cnt %d ** \n", __FUNCTION__,\
-                      cmd, ino, offset, uptodate, locked, count);\
-       }
+                      "locked: %s, cnt %d page %p ** \n", __FUNCTION__,\
+                      cmd, ino, offset, uptodate, locked, count, page);\
+       } else { CDEBUG(D_IOCTL, "** %s, no page\n", __FUNCTION__); }}
 
 
 #define OBD_ALLOC(ptr, cast, size)                                     \
@@ -126,7 +130,8 @@ static inline void inode_cpy(struct inode *dest, struct inode *src)
        /* allocation of space */
        dest->i_blocks = src->i_blocks;
 
-       memcpy(&dest->u, &src->u, sizeof(src->u));
+       if ( !dest->i_blocks) 
+               memcpy(&dest->u, &src->u, sizeof(src->u));
 }
 
 
index 109c706..51f9762 100644 (file)
@@ -34,6 +34,10 @@ int obdfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dent
 int obdfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry);
 /* dir.c */
 int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir);
+int obdfs_check_dir_entry (const char * function, struct inode * dir,
+                         struct ext2_dir_entry_2 * de,
+                         struct page * page,
+                          unsigned long offset);
 
 struct obdfs_sb_info {
        struct obd_conn_info osi_conn_info;
index bb76677..6973101 100644 (file)
@@ -199,8 +199,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
 
                CDEBUG(D_IOCTL, "Attach %d, type %s\n", 
                       dev, obddev->obd_type->typ_name);
-               if (!obddev->obd_type->typ_ops || 
-                   !obddev->obd_type->typ_ops->o_attach ) {
+               if (!obddev->obd_type->typ_ops || !OBP(obddev,attach)) {
                        obddev->obd_flags |=  OBD_ATTACHED;
                        type->typ_refcnt++;
                        MOD_INC_USE_COUNT;
@@ -208,8 +207,8 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                }
 
                /* do the attach */
-               err = obddev->obd_type->typ_ops->o_attach
-                       (obddev,  input.att_datalen, &input.att_data);
+               err = OBP(obddev,attach)(obddev,  
+                                        input.att_datalen, &input.att_data);
                OBD_FREE(input.att_data, input.att_datalen);
 
                if ( err ) {
@@ -322,8 +321,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                CDEBUG(D_IOCTL, "Setup %d, type %s\n", dev, 
                       obddev->obd_type->typ_name);
                if ( !obddev->obd_type->typ_ops || 
-                    !obddev->obd_type->typ_ops->o_setup )
-                       return -EOPNOTSUPP;
+                    !obddev->obd_type->typ_ops->o_setup ) {
+                       obddev->obd_flags |= OBD_SET_UP;
+                       return 0;
+               }
 
                err = obddev->obd_type->typ_ops->o_setup
                        (obddev, input.setup_datalen, input.setup_data);
@@ -334,7 +335,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                        obddev->obd_flags |= OBD_SET_UP;
                return err;
        }
-       case OBD_IOC_CLEANUP_OBDDEV: {
+       case OBD_IOC_CLEANUP: {
                int rc;
 
                /* has this minor been registered? */
@@ -348,7 +349,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                        goto cleanup_out;
 
                /* cleanup has no argument */
-               rc = obddev->obd_type->typ_ops->o_cleanup(obddev);
+               rc = OBP(obddev, cleanup)(obddev);
                if ( rc )
                        return rc;
 
@@ -383,10 +384,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
 
                get_user(cli_id, (int *) arg);
 
-               obddev->obd_type->typ_ops->o_disconnect(cli_id);
+               OBP(obddev, disconnect)(cli_id);
                return 0;
 
-       case OBD_IOC_SYNC:
+       case OBD_IOC_SYNC: {
                /* sync doesn't need a connection ID, because it knows
                 * what device it was called on, and can thus get the
                 * superblock that it needs. */
@@ -405,12 +406,17 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                }
 
                return put_user(err, (int *) arg);
-       case OBD_IOC_CREATE:
-               /* similarly, create doesn't need a connection ID for
-                * the same reasons. */
+       }
+       case OBD_IOC_CREATE: {
+               int err;
+               struct oic_create_s foo;
+
+               if ( copy_from_user(&foo, (const void *)arg, sizeof(foo)) )
+                       return -EFAULT;
 
                /* has this minor been registered? */
-               if (!obddev->obd_type)
+               if ( !(obddev->obd_flags & OBD_ATTACHED) ||
+                    !(obddev->obd_flags & OBD_SET_UP))
                        return -ENODEV;
 
 
@@ -419,7 +425,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                        return put_user(-EINVAL, (int *) arg);
                }
 
-               i_ino = obddev->obd_type->typ_ops->o_create(obddev, 0, &err);
+               i_ino = OBP(obddev, create)(foo.conn_id, foo.prealloc, &err);
                if (err) {
                        CDEBUG(D_IOCTL, "create: obd_inode_new failure\n");
                        /* 0 is the only error value */
@@ -427,6 +433,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                }
 
                return put_user(i_ino, (int *) arg);
+       }
        case OBD_IOC_DESTROY:
        {
                struct destroy_s {
@@ -449,18 +456,15 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
        case OBD_IOC_SETATTR:
        {
                int err;
-               struct tmp {
-                       unsigned int conn_id;
-                       unsigned long ino;
-                       struct iattr iattr;
-               } foo;
+               struct oic_attr_s foo;
                struct inode holder;
+
                /* has this minor been registered? */
                if (!obddev->obd_type)
                        return -ENODEV;
 
 
-               err= copy_from_user(&foo, (int *)arg, sizeof(struct tmp));
+               err= copy_from_user(&foo, (int *)arg, sizeof(foo));
                if (err)
                        return err;
 
@@ -715,7 +719,7 @@ int init_obd(void)
 
        for (i = 0; i < MAX_OBD_DEVICES; i++) {
                memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
-               INIT_LIST_HEAD(&obd_dev[i].u.sim.sim_clients);
+               INIT_LIST_HEAD(&obd_dev[i].obd_gen_clients);
        }
 
        obd_sysctl_init();
@@ -730,6 +734,16 @@ EXPORT_SYMBOL(obd_print_entry);
 EXPORT_SYMBOL(obd_debug_level);
 EXPORT_SYMBOL(obd_dev);
 
+EXPORT_SYMBOL(gen_connect);
+EXPORT_SYMBOL(gen_client);
+EXPORT_SYMBOL(gen_cleanup);
+EXPORT_SYMBOL(gen_disconnect);
+
+EXPORT_SYMBOL(gen_multi_attach);
+EXPORT_SYMBOL(gen_multi_setup);
+EXPORT_SYMBOL(gen_multi_cleanup);
+
+
 #ifdef MODULE
 int init_module(void)
 {
@@ -746,7 +760,7 @@ void cleanup_module(void)
                struct obd_device *obddev = &obd_dev[i];
                if ( obddev->obd_type && 
                     obddev->obd_type->typ_ops->o_cleanup_device )
-                       return obddev->obd_type->typ_ops->o_cleanup_device(i);
+                       OBP(obddev, cleanup_device)(obddev);
        }
 
        obd_sysctl_clean();
diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c
new file mode 100644 (file)
index 0000000..eb662b1
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ *  linux/fs/sim_obd/sim_obd.c
+ *
+ * These are the only exported functions; they provide the simulated object-
+ * oriented disk.
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <linux/sched.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+#include <linux/quotaops.h>
+#include <linux/list.h>
+#include <linux/file.h>
+#include <linux/iobuf.h>
+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+#include <linux/obd_support.h>
+#include <linux/obd_class.h>
+
+
+extern struct obd_device obd_dev[MAX_OBD_DEVICES];
+
+/* map connection to client */
+struct obd_client *gen_client(int cli_id)
+{
+       struct obd_device * obddev;
+       struct list_head * lh, * next;
+       struct obd_client * cli;
+       int a;
+
+       for (a = 0; a < MAX_OBD_DEVICES; a++) {
+               obddev = &obd_dev[a];
+
+               lh = next = &obddev->obd_gen_clients;
+               while ((lh = lh->next) != &obddev->obd_gen_clients) {
+                       cli = list_entry(lh, struct obd_client, cli_chain);
+                       
+                       if (cli->cli_id == cli_id)
+                               return cli;
+               }
+       }
+
+       return NULL;
+} /* obd_client */
+
+
+
+/* a connection defines a context in which preallocation can be managed. */ 
+int gen_connect (struct obd_device *obddev, 
+                       struct obd_conn_info * conninfo)
+{
+       struct obd_client * cli;
+
+       OBD_ALLOC(cli, struct obd_client *, sizeof(struct obd_client));
+       if ( !cli ) {
+               printk("obd_connect (minor %d): no memory!\n", 
+                      obddev->obd_minor);
+               return -ENOMEM;
+       }
+
+       INIT_LIST_HEAD(&cli->cli_prealloc_inodes);
+       /* this should probably spinlocked? */
+       cli->cli_id = ++obddev->obd_gen_last_id;
+       cli->cli_prealloc_quota = 0;
+       cli->cli_obd = obddev;
+       list_add(&(cli->cli_chain), obddev->obd_gen_clients.prev);
+
+       CDEBUG(D_IOCTL, "connect: new ID %u\n", cli->cli_id);
+       conninfo->conn_id = cli->cli_id;
+       return 0;
+} /* gen_obd_connect */
+
+
+int gen_disconnect(unsigned int conn_id)
+{
+       struct obd_client * cli;
+
+       ENTRY;
+
+       if (!(cli = gen_client(conn_id))) {
+               CDEBUG(D_IOCTL, "disconnect: attempting to free "
+                      "nonexistent client %u\n", conn_id);
+               return -EINVAL;
+       }
+
+       list_del(&(cli->cli_chain));
+       OBD_FREE(cli, sizeof(struct obd_client));
+
+       CDEBUG(D_IOCTL, "disconnect: ID %u\n", conn_id);
+
+       EXIT;
+       return 0;
+} /* gen_obd_disconnect */
+
+
+/* 
+ *   raid1 defines a number of connections to child devices,
+ *   used to make calls to these devices.
+ *   data holds nothing
+ */ 
+int gen_multi_setup(struct obd_device *obddev, int len, void *data)
+{
+       int i;
+       struct obd_device *rdev = obddev->obd_multi_dev[0];
+
+       for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
+               int rc;
+               struct obd_device *child = rdev + i;
+               rc  = OBP(child, connect)(child, &rdev->obd_multi_conns[i]);
+
+               if ( rc != 0 ) {
+                       /* XXX disconnect others */
+                       return -EINVAL;
+               }
+       }               
+       return 0;
+}
+
+int gen_multi_cleanup(struct obd_device * obddev)
+{
+       int i;
+       struct obd_device *rdev = obddev->obd_multi_dev[0];
+
+       for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
+               int rc;
+               struct obd_device *child = rdev + i;
+               rc  = OBP(child, cleanup)(child);
+               *child = -1;
+
+               if ( rc != 0 ) {
+                       /* XXX disconnect others */
+                       return -EINVAL;
+               }
+       }
+       gen_cleanup(obddev);
+       return 0;
+} /* sim_cleanup_obddev */
+
+
+int gen_multi_attach(struct obd_device *obddev, int len, void *data)
+{
+       int i;
+       int count;
+       struct obd_device *rdev = obddev->obd_multi_dev[0];
+
+       count = len/sizeof(int);
+       obddev->obd_multi_count = count;
+       for (i=0 ; i<count ; i++) {
+               rdev = &obd_dev[*((int *)data + i)];
+               rdev = rdev + 1;
+               CDEBUG(D_IOCTL, "OBD RAID1: replicator %d is of type %s\n", i,
+                      (rdev + i)->obd_type->typ_name);
+       }
+       return 0;
+}
+
+
+
+/*
+ *    remove all connections to this device
+ *    close all connections to lower devices
+ *    needed for forced unloads of OBD client drivers
+ */
+int gen_multi_cleanup_device(struct obd_device *obddev)
+{
+       int i;
+       struct obd_device *rdev;
+
+       rdev =  obddev->obd_multi_dev[0];
+       for (i = 0 ; i < obddev->obd_multi_count ; i++ ) {
+               int rc;
+               struct obd_device *child = rdev + i;
+               rc  = OBP(child, disconnect)
+                       (obddev->obd_multi_conns[i].conn_id);
+
+               if ( rc != 0 ) {
+                       printk("OBD multi cleanup dev: disconnect failure %d\n", child->obd_minor);
+               }
+               *child = 0;
+       }               
+       return 0;
+} /* gen_multi_cleanup_device */
+
+
+/*
+ *    forced cleanup of the device:
+ *    - remove connections from the device
+ *    - cleanup the device afterwards
+ */
+int gen_cleanup(struct obd_device * obddev)
+{
+       struct list_head * lh, * tmp;
+       struct obd_client * cli;
+
+       ENTRY;
+
+       lh = tmp = &obddev->obd_gen_clients;
+       while ((tmp = tmp->next) != lh) {
+               cli = list_entry(tmp, struct obd_client, cli_chain);
+               CDEBUG(D_IOCTL, "Disconnecting obd_connection %d, at %p\n",
+                      cli->cli_id, cli);
+               OBP(obddev, disconnect)(cli->cli_id);
+       }
+
+       return OBP(obddev, cleanup_device)(obddev);
+} /* sim_cleanup_device */
index 1928220..18d3360 100755 (executable)
@@ -23,8 +23,8 @@ eval 'sub OBD_IOC_CREATE () { &_IOC(2, ord(\'f\'), 3, 4);}' unless
   defined(&OBD_IOC_CREATE);
 eval 'sub OBD_IOC_SETUP_OBDDEV () { &_IOC(1, ord(\'f\'), 4, 4);}' unless
   defined(&OBD_IOC_SETUP_OBDDEV);
-eval 'sub OBD_IOC_CLEANUP_OBDDEV () { &_IOC(0, ord(\'f\'), 5, 0);}' unless
-  defined(&OBD_IOC_CLEANUP_OBDDEV);
+eval 'sub OBD_IOC_CLEANUP () { &_IOC(0, ord(\'f\'), 5, 0);}' unless
+  defined(&OBD_IOC_CLEANUP);
 eval 'sub OBD_IOC_DESTROY () { &_IOC(1, ord(\'f\'), 6, 4);}' unless
   defined(&OBD_IOC_DESTROY);
 eval 'sub OBD_IOC_PREALLOCATE () { &_IOC(3, ord(\'f\'), 7, 4);}' unless
@@ -71,22 +71,19 @@ use Carp;
 use Term::ReadLine;
 use IO::Handle;
 
-my ($device, $filesystem);
+
+my ($device, $filesystem, $file);
 # startup options (I'll replace these when I have some to replace with)
-GetOptions("device=s" => \$device, "fs=s" => $filesystem) || die "Getoptions";
+GetOptions("f!" => \$file, "device=s" => \$device, "fs=s" => $filesystem) || die "Getoptions";
 
 # genuine new simulated OBD device
-$device = "/dev/obd" unless $device;
+$device = "/dev/obd0" unless $device;
 # object store in the ext2 formatted block device
 $filesystem = "/dev/loop0" unless $filesystem;
 
-# get a console for the app
-my $term = new Term::ReadLine 'obdcontrol ';
-my $attribs = $term->Attribs;
-$term->ornaments('md,me,,');   # bold face prompt
 
-# make sure stdout is not buffered
-STDOUT->autoflush(1);
+
+# get a console for the app
 
 my $line;
 my $command;
@@ -121,7 +118,6 @@ my %commands =
 #
 my @jcm_cmd_list = keys %commands;
 
-$attribs->{attempted_completion_function} = \&completeme;
 #------------------------------------------------------------------------------
 # Open the device, as we need an FD for the ioctl
 sysopen(DEV_OBD, $device, 0) || die "Cannot open $device";
@@ -130,8 +126,26 @@ if (!defined($::st = stat($filesystem))) {
     die "Unable to stat $filesystem.\n";
 }
 
-# Get on with the show
-process_line();
+my $term, $attribs;
+
+if ( $file ) {
+       while ( <STDIN> ) {
+           print $_;
+           execute_line($_);
+       }
+       exit 0;
+} else {
+    $term = new Term::ReadLine 'obdcontrol ';
+    $attribs = $term->Attribs;
+    $attribs->{attempted_completion_function} = \&completeme;
+    $term->ornaments('md,me,,');       # bold face prompt
+    
+    # make sure stdout is not buffered
+    STDOUT->autoflush(1);
+
+    # Get on with the show
+    process_line();
+}
 
 #------------------------------------------------------------------------------
 sub completeme {
@@ -168,7 +182,12 @@ sub execute_line {
     my @arg = split(' ', $line);
     my $word = shift @arg;
 
-    my $cmd = find_command($word);
+    my $cmd;
+    if ( $file ) {
+       $cmd = $word;
+    } else {
+       $cmd = find_command($word);
+    }
     unless ($cmd) {
        printf STDERR "$word: No such command, or not unique.\n";
        return (-1);
@@ -283,6 +302,7 @@ sub Cleanup {
        print STDERR "ioctl failed: $!\n";
     } elsif ($rc eq "0 but true") {
        print "Finished (success)\n";
+       $::client_id = 0;
     } else {
        print "ioctl returned error code $rc.\n";
     }
@@ -338,16 +358,16 @@ sub Create {
     my $arg = shift;
     my $quiet = shift;
     my $rc;
+    my $prealloc = 0;
 
     if (defined($quiet) && !($quiet eq "quiet")) {
        print "syntax: create [number of objects [quiet]]\n";
        return;
     }
 
-    my $packed = pack("I", $::client_id);
+    my $packed = pack("IL", $::client_id, $prealloc);
     if (!defined($arg) || scalar($arg) < 2) {
        print "Creating 1 object...\n";
-       my $packed = pack("I", 0);
        $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $packed);
        if (!defined($quiet)) {
            my $ino = unpack("L", $packed);
diff --git a/lustre/obdclass/setup.sh b/lustre/obdclass/setup.sh
new file mode 100755 (executable)
index 0000000..6b5fbba
--- /dev/null
@@ -0,0 +1,13 @@
+#! /bin/bash
+
+insmod loop
+losetup /dev/loop0 /tmp/fs
+insmod obdclass.o
+insmod obdsim.o
+insmod ../obdfs/obdfs.o
+./obdcontrol -f << EOF
+attach sim_obd
+setup
+quit
+EOF
+mount -t obdfs /dev/loop0 /mnt/obd
index 0c0fe1c..fef4332 100644 (file)
@@ -47,37 +47,46 @@ static ssize_t obdfs_dir_read (struct file * filp, char * buf,
 {
        return -EISDIR;
 }
+#endif
 
-
-int ext2_check_dir_entry (const char * function, struct inode * dir,
+int obdfs_check_dir_entry (const char * function, struct inode * dir,
                          struct ext2_dir_entry_2 * de,
-                         struct buffer_head * bh,
+                         struct page * page,
                          unsigned long offset)
 {
        const char * error_msg = NULL;
 
+       ENTRY;
+       if ( !de ) {
+               error_msg = "null de passed";
+               return 1;
+       }
+
        if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(1))
                error_msg = "rec_len is smaller than minimal";
        else if (le16_to_cpu(de->rec_len) % 4 != 0)
                error_msg = "rec_len % 4 != 0";
        else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(de->name_len))
                error_msg = "rec_len is too small for name_len";
-       else if (dir && ((char *) de - bh->b_data) + le16_to_cpu(de->rec_len) >
+       else if (dir && ((char *) de - (char *)page_address(page)) + le16_to_cpu(de->rec_len) >
                 dir->i_sb->s_blocksize)
                error_msg = "directory entry across blocks";
-       else if (dir && le32_to_cpu(de->inode) > le32_to_cpu(dir->i_sb->u.ext2_sb.s_es->s_inodes_count))
-               error_msg = "inode out of bounds";
+#if 0 /* this one doesn't yet work for OBDFS */
+       else 
 
+if (dir && le32_to_cpu(de->inode) > le32_to_cpu(dir->i_sb->u.ext2_sb.s_es->s_inodes_count))
+               error_msg = "inode out of bounds";
+#endif
        if (error_msg != NULL)
                ext2_error (dir->i_sb, function, "bad entry in directory #%lu: %s - "
                            "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
                            dir->i_ino, error_msg, offset,
                            (unsigned long) le32_to_cpu(de->inode),
                            le16_to_cpu(de->rec_len), de->name_len);
+       EXIT;
        return error_msg == NULL ? 1 : 0;
 }
 
-#endif
 
 int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
@@ -98,6 +107,7 @@ int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 
        while (!error && !stored && filp->f_pos < inode->i_size) {
                page = obdfs_getpage(inode, offset, 0, NOLOCK);
+               PDEBUG(page, "readdir");
                if (!page) {
                        ext2_error (sb, "ext2_readdir",
                                    "directory #%lu contains a hole at offset %lu",
index fb6b916..ec31cef 100644 (file)
@@ -56,7 +56,7 @@ static inline void remove_suid(struct inode *inode)
 ssize_t obdfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
        ssize_t retval;
-       CDEBUG(D_INODE, "Writing %d bytes, offset %ld\n", count, (long)*ppos);
+       CDEBUG(D_INODE, "Writing inode %ld, %d bytes, offset %ld\n", file->f_dentry->d_inode->i_ino, count, (long)*ppos);
 
        retval = generic_file_write(file, buf, count,
                                    ppos, obdfs_write_one_page);
@@ -66,5 +66,6 @@ ssize_t obdfs_file_write(struct file *file, const char *buf, size_t count, loff_
                inode->i_ctime = inode->i_mtime = CURRENT_TIME;
                mark_inode_dirty(inode);
        }
+       EXIT;
        return retval;
 }
index 9738874..6d33286 100644 (file)
@@ -72,11 +72,12 @@ static inline int ext2_match (int len, const char * const name,
  */
 struct page * obdfs_find_entry (struct inode * dir,
                                             const char * const name, int namelen,
-                                            struct ext2_dir_entry_2 ** res_dir)
+                                            struct ext2_dir_entry_2 ** res_dir, int lock)
 {
        struct super_block * sb;
        unsigned long offset;
        struct page * page;
+       ENTRY;
 
        *res_dir = NULL;
        sb = dir->i_sb;
@@ -88,7 +89,7 @@ struct page * obdfs_find_entry (struct inode * dir,
                struct ext2_dir_entry_2 * de;
                char * dlimit;
 
-               page = obdfs_getpage(dir, offset, 0, NOLOCK);
+               page = obdfs_getpage(dir, offset, 0, lock);
                if ( !page ) 
                        return NULL;
 
@@ -103,12 +104,11 @@ struct page * obdfs_find_entry (struct inode * dir,
                            ext2_match (namelen, name, de)) {
                                /* found a match -
                                   just to be sure, do a full check */
-#if 0
-                               if (!ext2_check_dir_entry("ext2_find_entry",
-                                                         dir, de, bh, offset))
+                               if (!obdfs_check_dir_entry("ext2_find_entry",
+                                                         dir, de, page, offset))
                                        goto failure;
-#endif
                                *res_dir = de;
+                               EXIT;
                                return page;
                        }
                        /* prevent looping on a bad block */
@@ -124,6 +124,7 @@ struct page * obdfs_find_entry (struct inode * dir,
 
 failure:
        page_cache_release(page);
+       EXIT;
        return NULL;
 }
 
@@ -132,21 +133,32 @@ struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry)
        struct inode * inode;
        struct ext2_dir_entry_2 * de;
        struct page * page;
+       ENTRY;
 
        if (dentry->d_name.len > EXT2_NAME_LEN)
                return ERR_PTR(-ENAMETOOLONG);
 
-       page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
+       page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, NOLOCK);
        inode = NULL;
+       if ( !page ) 
+               CDEBUG(D_INODE, "No page - negative entry.\n");
+       if ( page && !de ) {
+               CDEBUG(D_INODE, "Danger: PAGE but de.\n");
+               return ERR_PTR(-ENOENT);
+       }
        if (page) {
                unsigned long ino = le32_to_cpu(de->inode);
                page_cache_release(page);
                inode = iget(dir->i_sb, ino);
 
-               if (!inode)
+               if (!inode) { 
+                       CDEBUG(D_INODE, "No inode.\n");
+                       EXIT;
                        return ERR_PTR(-EACCES);
+               }
        }
        d_add(dentry, inode);
+       EXIT;
        return NULL;
 }
 
@@ -174,6 +186,7 @@ static struct page *obdfs_add_entry (struct inode * dir,
        struct ext2_dir_entry_2 * de, * de1;
        struct super_block * sb;
 
+       ENTRY;
        *err = -EINVAL;
        *res_dir = NULL;
        if (!dir || !dir->i_nlink)
@@ -191,8 +204,10 @@ static struct page *obdfs_add_entry (struct inode * dir,
                return NULL;
        }
        page = obdfs_getpage(dir, 0, 0, LOCKED);
-       if (!page)
+       if (!page) {
+               EXIT;
                return NULL;
+       }
        rec_len = EXT2_DIR_REC_LEN(namelen);
        offset = 0;
        de = (struct ext2_dir_entry_2 *) page_address(page);
@@ -202,7 +217,7 @@ static struct page *obdfs_add_entry (struct inode * dir,
                        UnlockPage(page);
                        page_cache_release(page);
                        page = obdfs_getpage(dir, offset, 1, LOCKED);
-                       if (page)
+                       if (!page)
                                return NULL;
                        if (dir->i_size <= offset) {
                                if (dir->i_size == 0) {
@@ -214,7 +229,7 @@ static struct page *obdfs_add_entry (struct inode * dir,
 
                                de = (struct ext2_dir_entry_2 *) page_address(page);
                                de->inode = 0;
-                               de->rec_len = le16_to_cpu(sb->s_blocksize);
+                               de->rec_len = le16_to_cpu(PAGE_SIZE);
                                dir->i_size = offset + PAGE_SIZE;
                                dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
                                mark_inode_dirty(dir);
@@ -225,20 +240,23 @@ static struct page *obdfs_add_entry (struct inode * dir,
                                de = (struct ext2_dir_entry_2 *) page_address(page);
                        }
                }
-#if 0
-               if (!ext2_check_dir_entry ("ext2_add_entry", dir, de, bh,
+               CDEBUG(D_INODE, "\n");
+               if (!obdfs_check_dir_entry ("ext2_add_entry", dir, de, page,
                                           offset)) {
                        *err = -ENOENT;
-                       brelse (bh);
+                       page_cache_release(page);
+                       EXIT;
                        return NULL;
                }
-#endif
+               CDEBUG(D_INODE, "\n");
                if (ext2_match (namelen, name, de)) {
                                *err = -EEXIST;
                                UnlockPage(page);
                                page_cache_release(page);
+                               EXIT;
                                return NULL;
                }
+               CDEBUG(D_INODE, "\n");
                if ((le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) ||
                    (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) {
                        offset += le16_to_cpu(de->rec_len);
@@ -250,10 +268,12 @@ static struct page *obdfs_add_entry (struct inode * dir,
                                de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
                                de = de1;
                        }
+                       CDEBUG(D_INODE, "\n");
                        de->inode = 0;
                        de->name_len = namelen;
                        de->file_type = 0;
                        memcpy (de->name, name, namelen);
+                       CDEBUG(D_INODE, "\n");
                        /*
                         * XXX shouldn't update any times until successful
                         * completion of syscall, but too many callers depend
@@ -272,11 +292,14 @@ static struct page *obdfs_add_entry (struct inode * dir,
                        *res_dir = de;
                        *err = 0;
                        PDEBUG(page, "addentry");
+                       EXIT;
                        return page;
                }
+               CDEBUG(D_INODE, "\n");
                offset += le16_to_cpu(de->rec_len);
                de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        }
+       CDEBUG(D_INODE, "\n");
 
        UnlockPage(page);
        page_cache_release(page);
@@ -299,11 +322,9 @@ static int obdfs_delete_entry (struct ext2_dir_entry_2 * dir,
        pde = NULL;
        de = (struct ext2_dir_entry_2 *) page_address(page);
        while (i < PAGE_SIZE) {
-#if 0
-               if (!ext2_check_dir_entry ("ext2_delete_entry", NULL, 
-                                          de, bh, i))
+               if (!obdfs_check_dir_entry ("ext2_delete_entry", NULL, 
+                                          de, page, i))
                        return -EIO;
-#endif
                if (de == dir)  {
                        if (pde)
                                pde->rec_len =
@@ -363,12 +384,14 @@ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode)
        /*
         * N.B. Several error exits in ext2_new_inode don't set err.
         */
-       ino = sbi->osi_ops->o_create(sbi->osi_obd, 0, &err);
+       ino = sbi->osi_ops->o_create(sbi->osi_conn_info.conn_id, 0, &err);
        if ( ino == -1 ) 
                return -1;
        inode =  iget(dir->i_sb, ino);
-       if (!inode)
+       if (!inode) {
+               CDEBUG(D_INODE, "No inode, ino %ld\n", ino);
                return err;
+       }
 
        inode->i_op = &obdfs_inode_ops;
        inode->i_mode = mode;
@@ -378,6 +401,7 @@ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode)
                inode->i_nlink--;
                mark_inode_dirty(inode);
                iput (inode);
+               EXIT;
                return err;
        }
        de->inode = cpu_to_le32(inode->i_ino);
@@ -394,6 +418,7 @@ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode)
 #endif
        page_cache_release(page);
        d_instantiate(dentry, inode);
+       EXIT;
        return 0;
 }
 
@@ -413,7 +438,7 @@ int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
        /*
         * N.B. Several error exits in ext2_new_inode don't set err.
         */
-       ino = sbi->osi_ops->o_create(sbi->osi_obd, 0, &err);
+       ino = sbi->osi_ops->o_create(sbi->osi_conn_info.conn_id, 0, &err);
        if ( ino == -1 ) 
                return -1;
        inode =  iget(dir->i_sb, ino);
@@ -469,7 +494,7 @@ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
                goto out;
 
        err = -EIO;
-       ino = iops(dir)->o_create(sbi->osi_obd, 0, &err);
+       ino = iops(dir)->o_create(sbi->osi_conn_info.conn_id, 0, &err);
        if ( ino == -1 ) 
                return -1;
        child =  iget(dir->i_sb, ino);
@@ -499,7 +524,7 @@ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        
        de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        de->inode = cpu_to_le32(dir->i_ino);
-       de->rec_len = cpu_to_le16(child->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1));
+       de->rec_len = cpu_to_le16(PAGE_SIZE - EXT2_DIR_REC_LEN(1));
        de->name_len = 2;
        strcpy (de->name, "..");
        ext2_set_de_type(dir->i_sb, de, S_IFDIR);
@@ -546,6 +571,7 @@ out_no_entry:
        child->i_nlink = 0;
        mark_inode_dirty(child);
        iput (child);
+       EXIT;
        goto out;
 }
 
@@ -596,13 +622,11 @@ static int empty_dir (struct inode * inode)
                        }
                        de = (struct ext2_dir_entry_2 *) page_address(page);
                }
-#if 0
-               if (!ext2_check_dir_entry ("empty_dir", inode, de, bh,
+               if (!obdfs_check_dir_entry ("empty_dir", inode, de, page,
                                           offset)) {
-                       brelse (bh);
+                       page_cache_release(page);
                        return 1;
                }
-#endif
                if (le32_to_cpu(de->inode)) {
                        page_cache_release(page);
                        return 0;
@@ -626,7 +650,7 @@ int obdfs_rmdir (struct inode * dir, struct dentry *dentry)
        sbi = dir->i_sb->u.generic_sbp;
 
        retval = -ENOENT;
-       page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
+       page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED);
        if (!page)
                goto end_rmdir;
 
@@ -671,6 +695,7 @@ int obdfs_rmdir (struct inode * dir, struct dentry *dentry)
 end_rmdir:
        if ( page )
                page_cache_release(page);
+       EXIT;
        return retval;
 }
 
@@ -686,7 +711,7 @@ int obdfs_unlink(struct inode * dir, struct dentry *dentry)
        sbi = dir->i_sb->u.generic_sbp;
 
        retval = -ENOENT;
-       page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
+       page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED);
        if (!page)
                goto end_unlink;
 
@@ -728,6 +753,7 @@ int obdfs_unlink(struct inode * dir, struct dentry *dentry)
 end_unlink:
        if (page)
                page_cache_release(page);
+       EXIT;
        return retval;
 }
 
@@ -748,7 +774,7 @@ int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symna
        /*
         * N.B. Several error exits in ext2_new_inode don't set err.
         */
-       ino = sbi->osi_ops->o_create(sbi->osi_obd, 0, &err);
+       ino = sbi->osi_ops->o_create(sbi->osi_conn_info.conn_id, 0, &err);
        if ( ino == -1 ) 
                return -1;
        inode =  iget(dir->i_sb, ino);
@@ -872,7 +898,7 @@ int obdfs_link (struct dentry * old_dentry,
  * higher-level routines.
  */
 int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
-                          struct inode * new_dir,struct dentry *new_dentry)
+                          struct inode * new_dir, struct dentry *new_dentry)
 {
        struct inode * old_inode, * new_inode;
        struct page * old_page, * new_page, * dir_page;
@@ -885,7 +911,9 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
 
        new_page = dir_page = NULL;
 
-       old_page = obdfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de);
+       /* does the old entry exist? - if not get out */
+       old_page = obdfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de, NOLOCK);
+       PDEBUG(old_page, "rename - old page");
        /*
         *  Check for inode number is _not_ due to possible IO errors.
         *  We might rmdir the source, keep it as pwd of some process
@@ -897,9 +925,11 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
        if (!old_page || le32_to_cpu(old_de->inode) != old_inode->i_ino)
                goto end_rename;
 
+       /* find new inode */
        new_inode = new_dentry->d_inode;
        new_page = obdfs_find_entry (new_dir, new_dentry->d_name.name,
-                               new_dentry->d_name.len, &new_de);
+                               new_dentry->d_name.len, &new_de, NOLOCK);
+       PDEBUG(new_page, "rename - new page ");
        if (new_page) {
                if (!new_inode) {
                        page_cache_release(new_page);
@@ -908,7 +938,9 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
                        DQUOT_INIT(new_inode);
                }
        }
+       /* in this case we to check more ... */
        if (S_ISDIR(old_inode->i_mode)) {
+               /* can only rename into empty new directory */
                if (new_inode) {
                        retval = -ENOTEMPTY;
                        if (!empty_dir (new_inode))
@@ -916,6 +948,8 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
                }
                retval = -EIO;
                dir_page= obdfs_getpage (old_inode, 0, 0, LOCKED);
+               PDEBUG(dir_page, "rename dir page");
+
                if (!dir_page)
                        goto end_rename;
                if (le32_to_cpu(PARENT_INO(page_address(dir_page))) != old_dir->i_ino)
@@ -925,17 +959,19 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
                                new_dir->i_nlink >= EXT2_LINK_MAX)
                        goto end_rename;
        }
+       /* create the target dir entry */
        if (!new_page) {
                new_page = obdfs_add_entry (new_dir, new_dentry->d_name.name,
                                        new_dentry->d_name.len, &new_de,
                                        &retval);
+               PDEBUG(new_page, "rename new page");
                if (!new_page)
                        goto end_rename;
        }
        new_dir->i_version = ++event;
 
        /*
-        * ok, that's it
+        * remove the old entry
         */
        new_de->inode = le32_to_cpu(old_inode->i_ino);
        if (EXT2_HAS_INCOMPAT_FEATURE(new_dir->i_sb,
@@ -956,7 +992,7 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
        if (dir_page) {
                PARENT_INO(page_address(dir_page)) = le32_to_cpu(new_dir->i_ino);
                sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
-                           new_dir->i_ino, dir_page, 0);
+                           old_inode->i_ino, dir_page, 0);
                old_dir->i_nlink--;
                mark_inode_dirty(old_dir);
                if (new_inode) {
@@ -968,8 +1004,16 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
                        mark_inode_dirty(new_dir);
                }
        }
-       sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
-                           old_inode->i_ino, old_page, 0);
+       if ( old_page != new_page ) {
+               unsigned long offset = old_page->offset;
+               /* lock the old_page and release unlocked copy */
+               CDEBUG(D_INODE, "old_page at %p\n", old_page);
+               page_cache_release(old_page);
+               old_page = obdfs_getpage(old_dir, offset, 0, LOCKED);
+               CDEBUG(D_INODE, "old_page at %p\n", old_page);
+               sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
+                                   old_dir->i_ino, old_page, 0);
+       }
 #if 0
        if (IS_SYNC(old_dir)) {
                ll_rw_block (WRITE, 1, &old_bh);
@@ -977,7 +1021,7 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
        }
 #endif
        sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
-                           new_inode->i_ino, new_page, 0);
+                           new_dir->i_ino, new_page, 0);
 #if 0
        if (IS_SYNC(new_dir)) {
                ll_rw_block (WRITE, 1, &new_bh);
@@ -988,11 +1032,19 @@ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
        retval = 0;
 
 end_rename:
+       if (old_page && PageLocked(old_page) )
+               UnlockPage(old_page);
        if (old_page)
                page_cache_release(old_page);
+       if (new_page && PageLocked(new_page) )
+               UnlockPage(new_page);
        if (new_page)
                page_cache_release(new_page);
+       if (dir_page && PageLocked(dir_page) )
+               UnlockPage(dir_page);
        if (dir_page)
                page_cache_release(dir_page);
+
+
        return retval;
 }
index ff06852..4016b49 100644 (file)
@@ -73,6 +73,7 @@ int obdfs_write_one_page(struct file *file, struct page *page, unsigned long off
        long status;
         struct obdfs_sb_info *sbi = file->f_dentry->d_inode->i_sb->u.generic_sbp;
 
+       ENTRY;
        if ( !Page_Uptodate(page) ) {
                status =  sbi->osi_ops->o_brw(READ, 
                                              sbi->osi_conn_info.conn_id, 
@@ -92,6 +93,7 @@ int obdfs_write_one_page(struct file *file, struct page *page, unsigned long off
                status = obdfs_writepage(file, page);
                unlock_kernel();
        }
+       EXIT;
        if ( status != PAGE_SIZE ) 
                return status;
        else
@@ -140,6 +142,7 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create
                PDEBUG(page,"GETPAGE");
                if (!locked)
                        UnlockPage(page);
+               EXIT;
                return page;
        } 
                
@@ -147,7 +150,7 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create
                CDEBUG(D_INODE, "Page found but not up to date\n");
        }
 
-       /* page_cache_alloc returns address of page */
+       /* page_cache_alloc returns the VM address of page */
        new_page = page_cache_alloc();
        if (!new_page)
                return NULL;
@@ -155,16 +158,16 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create
        /* corresponding struct page in the mmap */
        hash = page_hash(inode, offset);
        page = page_cache_entry(new_page);
-       PDEBUG(page, "GETPAGE");
        if (!add_to_page_cache_unique(page, inode, offset, hash)) {
                CDEBUG(D_INODE, "Page not found. Reading it.\n");
-               PDEBUG(page,"GETPAGE");
+               PDEBUG(page,"GETPAGE - before reading");
                sbi->osi_ops->o_brw(READ, sbi->osi_conn_info.conn_id, 
                                    inode->i_ino, page, create);
                if ( !locked )
                        UnlockPage(page);
                SetPageUptodate(page);
-               PDEBUG(page,"GETPAGE");
+               PDEBUG(page,"GETPAGE - after reading");
+               EXIT;
                return page;
        }
        /*
@@ -173,6 +176,7 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create
         */
        CDEBUG(D_INODE, "Page not found. Someone raced us.\n");
        PDEBUG(page,"GETPAGE");
+       EXIT;
        return page;
 }
 
index 0072f36..eddd0c8 100644 (file)
@@ -66,6 +66,7 @@ static struct super_block * obdfs_read_super(struct super_block *sb,
 {
         struct inode *root = 0; 
        struct obdfs_sb_info *sbi = NULL;
+       struct obd_device *obddev;
         int error = 0;
        unsigned long blocksize;
        unsigned long blocksize_bits;
@@ -83,8 +84,14 @@ static struct super_block * obdfs_read_super(struct super_block *sb,
                MOD_DEC_USE_COUNT;
                return NULL;
        }
+       
+       obddev = &obd_dev[obd_minor];
+
+       if ( ! (obddev->obd_flags & OBD_ATTACHED) || 
+            ! (obddev->obd_flags & OBD_SET_UP) )
+               return NULL;
 
-       sbi->osi_obd = &obd_dev[obd_minor];
+       sbi->osi_obd = obddev;
        sbi->osi_ops = sbi->osi_obd->obd_type->typ_ops;
        
         error  = sbi->osi_ops->o_connect(sbi->osi_obd, &sbi->osi_conn_info);
diff --git a/lustre/patches/patch-2.3.21 b/lustre/patches/patch-2.3.21
new file mode 100644 (file)
index 0000000..b0c4712
--- /dev/null
@@ -0,0 +1,60 @@
+--- linux/kernel/ksyms.c.or    Tue Oct 12 10:40:21 1999
++++ linux/kernel/ksyms.c       Tue Oct 12 11:22:45 1999
+@@ -36,6 +36,7 @@
+ #include <linux/swap.h>
+ #include <linux/ctype.h>
+ #include <linux/file.h>
++#include <linux/iobuf.h>
+ #include <linux/console.h>
+ #include <linux/poll.h>
+ #include <linux/mm.h>
+@@ -118,6 +119,8 @@
+ EXPORT_SYMBOL(update_atime);
+ EXPORT_SYMBOL(get_super);
+ EXPORT_SYMBOL(get_fs_type);
++EXPORT_SYMBOL(get_empty_super);
++EXPORT_SYMBOL(remove_vfsmnt);
+ EXPORT_SYMBOL(getname);
+ EXPORT_SYMBOL(_fput);
+ EXPORT_SYMBOL(igrab);
+@@ -140,6 +143,9 @@
+ EXPORT_SYMBOL(d_path);
+ EXPORT_SYMBOL(__mark_buffer_dirty);
+ EXPORT_SYMBOL(__mark_inode_dirty);
++EXPORT_SYMBOL(free_kiovec);
++EXPORT_SYMBOL(brw_kiovec);
++EXPORT_SYMBOL(alloc_kiovec);
+ EXPORT_SYMBOL(get_empty_filp);
+ EXPORT_SYMBOL(init_private_file);
+ EXPORT_SYMBOL(filp_open);
+--- linux/fs/super.c.or        Tue Oct 12 10:39:05 1999
++++ linux/fs/super.c   Tue Oct 12 11:18:14 1999
+@@ -135,7 +135,7 @@
+       return lptr;
+ }
+-static void remove_vfsmnt(kdev_t dev)
++void remove_vfsmnt(kdev_t dev)
+ {
+       struct vfsmount *lptr, *tofree;
+@@ -508,7 +508,7 @@
+ /*
+  * Find a super_block with no device assigned.
+  */
+-static struct super_block *get_empty_super(void)
++struct super_block *get_empty_super(void)
+ {
+       struct super_block *s;
+--- linux/include/linux/fs.h.or        Tue Oct 12 10:39:59 1999
++++ linux/include/linux/fs.h   Tue Oct 12 11:32:46 1999
+@@ -934,6 +934,8 @@
+ extern struct super_block *get_super(kdev_t);
++struct super_block *get_empty_super(void);
++void remove_vfsmnt(kdev_t dev);
+ extern void put_super(kdev_t);
+ unsigned long generate_cluster(kdev_t, int b[], int);
+ unsigned long generate_cluster_swab32(kdev_t, int b[], int);