Whamcloud - gitweb
Numerous fixes, including the attach code, better page locking etc.
authorbraam <braam>
Wed, 13 Oct 1999 03:29:34 +0000 (03:29 +0000)
committerbraam <braam>
Wed, 13 Oct 1999 03:29:34 +0000 (03:29 +0000)
lustre/include/linux/obd_class.h
lustre/include/linux/obd_support.h
lustre/include/linux/obdfs.h
lustre/obdclass/class_obd.c
lustre/obdclass/obdcontrol
lustre/obdfs/dir.c
lustre/obdfs/namei.c
lustre/obdfs/rw.c
lustre/obdfs/super.c

index f7d6f22..200e45b 100644 (file)
@@ -14,10 +14,6 @@ extern struct obd_device obd_dev[MAX_OBD_DEVICES];
 
 struct obd_conn_info {
        unsigned int conn_id;     /* handle */
-       unsigned long conn_ino;   /* root inode number */
-       /* XXX do we really need this */
-       unsigned long conn_blocksize; 
-       unsigned char conn_blocksize_bits;
 };
 
 struct obd_type {
@@ -27,9 +23,14 @@ struct obd_type {
        int  typ_refcnt;
 };
 
+#define OBD_ATTACHED 0x1
+#define OBD_SET_UP   0x2
+
 /* corresponds to one of the obdx */
 struct obd_device {
        struct obd_type *obd_type;
+       int obd_minor;
+       int obd_flags;
        int obd_refcnt; 
        union {
                struct sim_obd sim;
@@ -37,34 +38,35 @@ struct obd_device {
        } u;
 };
 
-#define OBD_FL_SETUP 0x1
-
 struct obd_ops {
-       int (*o_format)(void);
-       int (*o_partition)(int partition, unsigned int size);
-       int (*o_connect)(int minor, struct obd_conn_info *info);
+       int (*o_attach)(struct obd_device *, int len, void *);
+       int (*o_format)(struct obd_device *, int len, void *);
+       int (*o_partition)(struct obd_device *, int len, void *);
+       int (*o_connect)(struct obd_device *, struct obd_conn_info *info);
        int (*o_disconnect)(unsigned int conn_id);
-       int (*o_setup) (struct obd_device *dev, void *data);
+       int (*o_setup) (struct obd_device *dev, int len, void *data);
        int (*o_cleanup)(struct obd_device *dev);
-       int (*o_setattr)(unsigned int conn_id, unsigned long id, struct iattr *iattr);
-       int (*o_getattr)(unsigned int conn_id, unsigned long id, struct iattr *iattr);
+       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_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 (*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_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);
 };
 
 int obd_register_type(struct obd_ops *ops, char *nm);
-
+int obd_unregister_type(char *nm);
 
 struct obd_client {
        struct list_head cli_chain;
-       kdev_t minor;
+       struct obd_device *cli_obd;
        unsigned int cli_id;
        unsigned long cli_prealloc_quota;
        struct list_head cli_prealloc_inodes;
@@ -78,6 +80,13 @@ struct obd_prealloc_inode {
 /*
  * ioctl commands
  */
+struct oic_attach {
+       int  att_typelen;
+       void *att_type;
+       int  att_datalen;
+       void *att_data;
+};
+
 struct oic_prealloc_s {
        unsigned long cli_id;
        unsigned long alloc; /* user sets it to the number of inodes requesting
@@ -119,8 +128,9 @@ struct oic_partition {
 #define OBD_IOC_STATFS                 _IOWR('f', 15, long)
 #define OBD_IOC_SYNC                   _IOR ('f',  16, long)
 #define OBD_IOC_READ2                  _IOWR('f', 17, long)
-#define OBD_IOC_FORMAT                 _IO('f', 17, long)
-#define OBD_IOC_READ2                  _IOWR('f', 17, long)
+#define OBD_IOC_FORMAT                 _IOWR('f', 18, long)
+#define OBD_IOC_PARTITION              _IOWR('f', 19, long)
+#define OBD_IOC_ATTACH                 _IOWR('f', 20, long)
 
 #define OBD_IOC_DEC_FS_USE_COUNT       _IO  ('f', 32      )
 
index 2c6e664..4e2c6e5 100644 (file)
@@ -50,16 +50,19 @@ extern int obd_print_entry;
 
 #endif /* SIM_OBD_DEBUG */
 
+
+#define CMD(cmd) (( cmd == READ ) ? "read" : "write")
+
 #define PDEBUG(page,cmd)       {\
-               char *command = ( cmd == READ ) ? "read" : "write";\
                char *uptodate = (Page_Uptodate(page)) ? "yes" : "no";\
                char *locked = (PageLocked(page)) ? "yes" : "no";\
                int count = page->count.counter;\
                long ino = (page->inode) ? page->inode->i_ino : -1;\
+                long offset = page->offset / PAGE_SIZE;\
                \
-               CDEBUG(D_IOCTL, " ** %s, cmd: %s, ino: %ld, uptodate: %s, "\
+               CDEBUG(D_IOCTL, " ** %s, cmd: %s, ino: %ld, off %ld, uptodate: %s, "\
                       "locked: %s, cnt %d ** \n", __FUNCTION__,\
-                      command, ino, uptodate, locked, count);\
+                      cmd, ino, offset, uptodate, locked, count);\
        }
 
 
@@ -94,4 +97,45 @@ do {                                                 \
        }                                               \
 } while (0)
 
+
+
+static inline void inode_to_iattr(struct inode *inode, struct iattr *tmp)
+{
+       tmp->ia_mode = inode->i_mode;
+       tmp->ia_uid = inode->i_uid;
+       tmp->ia_gid = inode->i_gid;
+       tmp->ia_size = inode->i_size;
+       tmp->ia_atime = inode->i_atime;
+       tmp->ia_mtime = inode->i_mtime;
+       tmp->ia_ctime = inode->i_ctime;
+       tmp->ia_attr_flags = inode->i_flags;
+
+       tmp->ia_valid = ~0;
+}
+
+static inline void inode_cpy(struct inode *dest, struct inode *src)
+{
+       dest->i_mode = src->i_mode;
+       dest->i_uid = src->i_uid;
+       dest->i_gid = src->i_gid;
+       dest->i_size = src->i_size;
+       dest->i_atime = src->i_atime;
+       dest->i_mtime = src->i_mtime;
+       dest->i_ctime = src->i_ctime;
+       dest->i_attr_flags = src->i_flags;
+       /* allocation of space */
+       dest->i_blocks = src->i_blocks;
+
+       memcpy(&dest->u, &src->u, sizeof(src->u));
+}
+
+
+
+
+
+
+
+
+
+
 #endif
index cee9b7b..109c706 100644 (file)
@@ -18,13 +18,20 @@ ssize_t obdfs_file_write(struct file *file, const char *buf, size_t count, loff_
 
 
 /* rw.c */
-struct page *obdfs_getpage(struct inode *inode, unsigned long offset);
+struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create, int locked);
 int obdfs_writepage(struct file *file, struct page *page);
 int obdfs_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf);
 
 /* namei.c */
 struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry);
-
+int obdfs_create (struct inode * dir, struct dentry * dentry, int mode);
+int obdfs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+int obdfs_rmdir(struct inode *dir, struct dentry *dentry);
+int obdfs_unlink(struct inode *dir, struct dentry *dentry);
+int obdfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev);
+int obdfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
+int obdfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry);
+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);
 
@@ -40,8 +47,17 @@ void obdfs_sysctl_clean(void);
 
 struct obdfs_inode_info;
 
-extern struct file_operations obdfs_file_operations;
-extern struct inode_perations obdfs_inode_operations;
+extern struct file_operations obdfs_file_ops;
+extern struct inode_operations obdfs_inode_ops;
+
+static inline struct obd_ops *iops(struct inode *i)
+{
+       struct obdfs_sb_info *sbi = (struct obdfs_sb_info *) i->i_sb->u.generic_sbp;
+       return sbi->osi_ops;
+}
+
+#define NOLOCK 0
+#define LOCKED 1
 
 
 #define OBDFS_SUPER_MAGIC 0x4711
index 56cf3f3..bb76677 100644 (file)
@@ -122,6 +122,28 @@ static struct obd_type *obd_nm_to_type(char *nm)
        return NULL;
 }
 
+
+static int getdata(int len, void **data)
+{
+       void *tmp = NULL;
+
+       if (!len) 
+               return 0;
+
+       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 */
 static int obd_class_ioctl (struct inode * inode, struct file * filp, 
                            unsigned int cmd, unsigned long arg)
@@ -132,72 +154,206 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
        long int cli_id; /* connect, disconnect */
 
        struct oic_prealloc_s prealloc; /* preallocate */
+
        if (!inode)
                return -EINVAL;
+
        dev = MINOR(inode->i_rdev);
        if (dev > MAX_OBD_DEVICES)
                return -ENODEV;
-
        obddev = &obd_dev[dev];
 
-       /* has this minor been registered? */
-       if (cmd != OBD_IOC_SETUP_OBDDEV && !obd_dev[dev].obd_type)
-               return -ENODEV;
-
        switch (cmd) {
-       case OBD_IOC_SETUP_OBDDEV: {
+       case OBD_IOC_ATTACH: {
                struct obd_type *type;
+               struct oic_attach input;
 
-               struct setup {
-                       int  setup_data;
-                       char setup_type[24];
-               } input;
-
-               if ( obddev->obd_type ) {
-                       CDEBUG(D_IOCTL, "Device %d already setup (type %s)\n",
-                              dev, obddev->obd_type->typ_name);
-                       return -1;
+               /* have we attached a type to this device */
+               if ( obddev->obd_type || (obddev->obd_flags & OBD_ATTACHED) ){
+                       CDEBUG(D_IOCTL, "OBD Device %d already attached to type %s.\n", dev, obddev->obd_type->typ_name);
+                       return -EINVAL;
                }
 
                /* get data structures */
-               err= copy_from_user(&input, (void *) arg, sizeof(input));
+               err = copy_from_user(&input, (void *) arg, sizeof(input));
                if (err)
                        return err;
 
-               type = obd_nm_to_type(input.setup_type);
+               if ( (err = getdata(input.att_typelen + 1, &input.att_type)) )
+                       return err;
+
+               /* find the type */
+               err = -EINVAL;
+               type = obd_nm_to_type(input.att_type);
+               OBD_FREE(input.att_type, input.att_typelen + 1);
                if ( !type ) {
-                       printk("Trying to register non existent type %s\n",
-                              input.setup_type);
-                       return -1;
+                       printk("Unknown obd type dev %d\n", dev);
+                       return err;
                }
                obddev->obd_type = type;
+               
+               /* get the attach data */
+               if ( (err = getdata(input.att_datalen, &input.att_data)) ) {
+                       return err;
+               }
+
+               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 ) {
+                       obddev->obd_flags |=  OBD_ATTACHED;
+                       type->typ_refcnt++;
+                       MOD_INC_USE_COUNT;
+                       return 0;
+               }
 
-               CDEBUG(D_IOCTL, "Setup %d, type %s\n", dev, input.setup_type);
-               if ( obddev->obd_type->typ_ops->o_setup(obddev, 
-                                                       &input.setup_data)){
+               /* do the attach */
+               err = obddev->obd_type->typ_ops->o_attach
+                       (obddev,  input.att_datalen, &input.att_data);
+               OBD_FREE(input.att_data, input.att_datalen);
+
+               if ( err ) {
+                       obddev->obd_flags &= ~OBD_ATTACHED;
                        obddev->obd_type = NULL;
-                       return -1;
                } else {
+                       obddev->obd_flags |=  OBD_ATTACHED;
                        type->typ_refcnt++;
                        MOD_INC_USE_COUNT;
-                       return 0;
                }
+               return err;
+       }
+       case OBD_IOC_FORMAT: {
+               struct ioc_format {
+                       int format_datalen;
+                       void *format_data;
+               } input;
+
+               /* have we attached a type to this device */
+               if ( !obddev->obd_type ) {
+                       CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
+                       return -EINVAL;
+               }
+
+               /* get main structure */
+               err = copy_from_user(&input, (void *) arg, sizeof(input));
+               if (err) 
+                       return err;
+
+               err = getdata(input.format_datalen, &input.format_data);
+               if (err) 
+                       return err;
+
+               if (!obddev->obd_type->typ_ops || 
+                   !obddev->obd_type->typ_ops->o_format )
+                       return -EOPNOTSUPP;
+
+               /* do the format */
+               CDEBUG(D_IOCTL, "Format %d, type %s\n", dev, 
+                      obddev->obd_type->typ_name);
+               err = obddev->obd_type->typ_ops->o_format
+                       (obddev, input.format_datalen, input.format_data);
+
+               OBD_FREE(input.format_data, input.format_datalen);
+               return err;
+       }
+       case OBD_IOC_PARTITION: {
+               struct ioc_part {
+                       int part_datalen;
+                       void *part_data;
+               } input;
+
+               /* have we attached a type to this device */
+               if ( !obddev->obd_type ) {
+                       CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
+                       return -EINVAL;
+               }
+
+               /* get main structure */
+               err = copy_from_user(&input, (void *) arg, sizeof(input));
+               if (err) 
+                       return err;
+
+               err = getdata(input.part_datalen, &input.part_data);
+               if (err) 
+                       return err;
+
+               if (!obddev->obd_type->typ_ops || 
+                   !obddev->obd_type->typ_ops->o_partition )
+                       return -EOPNOTSUPP;
+
+               /* do the partition */
+               CDEBUG(D_IOCTL, "Partition %d, type %s\n", dev, 
+                      obddev->obd_type->typ_name);
+               err = obddev->obd_type->typ_ops->o_partition
+                       (obddev, input.part_datalen, input.part_data);
+
+               OBD_FREE(input.part_data, input.part_datalen);
+               return err;
+       }
+       case OBD_IOC_SETUP_OBDDEV: {
+               struct ioc_setup {
+                       int setup_datalen;
+                       void *setup_data;
+               } input;
+
+               /* have we attached a type to this device */
+               if (!(obddev->obd_flags & OBD_ATTACHED)) {
+                       CDEBUG(D_IOCTL, "OBD Device %d has no type.\n", dev);
+                       return -EINVAL;
+               }
+
+               /* 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);
+                       return -EINVAL;
+               }
+
+               /* get main structure */
+               err = copy_from_user(&input, (void *) arg, sizeof(input));
+               if (err) 
+                       return err;
+
+               err = getdata(input.setup_datalen, &input.setup_data);
+               if (err) 
+                       return err;
+
+               /* do the setup */
+               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;
+
+               err = obddev->obd_type->typ_ops->o_setup
+                       (obddev, input.setup_datalen, input.setup_data);
+
+               if ( err ) 
+                       obddev->obd_flags &= ~OBD_SET_UP;
+               else 
+                       obddev->obd_flags |= OBD_SET_UP;
+               return err;
        }
        case OBD_IOC_CLEANUP_OBDDEV: {
                int rc;
 
+               /* has this minor been registered? */
+               if (!obddev->obd_type)
+                       return -ENODEV;
+
                if ( !obddev->obd_type->typ_refcnt ) 
                        printk("OBD_CLEANUP: refcount wrap!\n");
 
                if ( !obddev->obd_type->typ_ops->o_cleanup )
-                       goto out;
+                       goto cleanup_out;
 
                /* cleanup has no argument */
                rc = obddev->obd_type->typ_ops->o_cleanup(obddev);
                if ( rc )
                        return rc;
 
-               out: 
+       cleanup_out: 
+               obddev->obd_flags = 0;
                obddev->obd_type->typ_refcnt--;
                obddev->obd_type = NULL;
                MOD_DEC_USE_COUNT;
@@ -207,7 +363,13 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
        {
                struct obd_conn_info conninfo;
 
-               if (obddev->obd_type->typ_ops->o_connect(dev, &conninfo))
+               if ( (!(obddev->obd_flags & OBD_SET_UP)) ||
+                    (!(obddev->obd_flags & OBD_ATTACHED))) {
+                       CDEBUG(D_IOCTL, "Device not attached or set up\n");
+                       return -EINVAL;
+               }
+
+               if (obddev->obd_type->typ_ops->o_connect(obddev, &conninfo))
                        return -EINVAL;
 
                return copy_to_user((int *)arg, &conninfo,
@@ -215,6 +377,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
        }
        case OBD_IOC_DISCONNECT:
                /* frees data structures */
+               /* has this minor been registered? */
+               if (!obddev->obd_type)
+                       return -ENODEV;
+
                get_user(cli_id, (int *) arg);
 
                obddev->obd_type->typ_ops->o_disconnect(cli_id);
@@ -224,6 +390,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                /* 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. */
+               /* has this minor been registered? */
+               if (!obddev->obd_type)
+                       return -ENODEV;
+
                if (!obddev->u.sim.sim_sb || !obddev->u.sim.sim_sb->s_dev) {
                        CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
                        err = -EINVAL;
@@ -238,6 +408,12 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
        case OBD_IOC_CREATE:
                /* similarly, create doesn't need a connection ID for
                 * the same reasons. */
+
+               /* has this minor been registered? */
+               if (!obddev->obd_type)
+                       return -ENODEV;
+
+
                if (!obddev->u.sim.sim_sb) {
                        CDEBUG(D_IOCTL, "fatal: device not initialized.\n");
                        return put_user(-EINVAL, (int *) arg);
@@ -257,6 +433,12 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                        unsigned int conn_id;
                        unsigned int ino;
                } destroy;
+
+               /* has this minor been registered? */
+               if (!obddev->obd_type)
+                       return -ENODEV;
+
+
                copy_from_user(&destroy, (int *)arg, sizeof(struct destroy_s));
                if ( !obddev->obd_type ||
                     !obddev->obd_type->typ_ops->o_destroy)
@@ -272,6 +454,11 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                        unsigned long ino;
                        struct iattr iattr;
                } 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));
                if (err)
@@ -280,8 +467,9 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                if ( !obddev->obd_type ||
                     !obddev->obd_type->typ_ops->o_setattr)
                        return -EINVAL;
-
-               return obddev->obd_type->typ_ops->o_setattr(foo.conn_id, foo.ino, &foo.iattr);
+               
+               inode_setattr(&holder, &foo.iattr);
+               return obddev->obd_type->typ_ops->o_setattr(foo.conn_id, foo.ino, &holder);
        }
 
        case OBD_IOC_GETATTR:
@@ -292,6 +480,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                        unsigned long ino;
                } foo;
                struct iattr iattr;
+               struct inode holder;
                copy_from_user(&foo, (int *)arg, sizeof(struct tmp));
 
                if ( !obddev->obd_type ||
@@ -299,9 +488,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                        return -EINVAL;
 
                if (obddev->obd_type->typ_ops->o_getattr(foo.conn_id, 
-                                                        foo.ino, &iattr))
+                                                        foo.ino, &holder))
                        return -EINVAL;
 
+               inode_to_iattr(&holder, &iattr);
                err = copy_to_user((int *)arg, &iattr, sizeof(iattr));
                return err;
        }
@@ -310,6 +500,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
        {
                int err;
 
+               /* has this minor been registered? */
+               if (!obddev->obd_type)
+                       return -ENODEV;
+
                err = copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
                if ( err ) 
                        return err;
@@ -336,6 +530,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
        case OBD_IOC_READ:
        {
                int err;
+               /* has this minor been registered? */
+               if (!obddev->obd_type)
+                       return -ENODEV;
+
 
                err = copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
                if ( err ) 
@@ -362,6 +560,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
        case OBD_IOC_WRITE:
        {
                int err;
+               /* has this minor been registered? */
+               if (!obddev->obd_type)
+                       return -ENODEV;
+
 
                copy_from_user(&rw_s, (int *)arg, sizeof(struct oic_rw_s));
                CDEBUG(D_IOCTL, "\n");
@@ -382,6 +584,11 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                return err;
        }
        case OBD_IOC_PREALLOCATE:
+               /* has this minor been registered? */
+               if (!obddev->obd_type)
+                       return -ENODEV;
+
+
                copy_from_user(&prealloc, (int *)arg,
                               sizeof(struct oic_prealloc_s));
 
@@ -408,6 +615,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                struct statfs buf;
                int rc;
 
+               /* has this minor been registered? */
+               if (!obddev->obd_type)
+                       return -ENODEV;
+
                tmp = (void *)arg + sizeof(unsigned int);
                get_user(conn_id, (int *) arg);
                if ( !obddev->obd_type ||
@@ -422,7 +633,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp,
                
        }
        default:
-               printk("invalid ioctl: cmd = %u, arg = %lu\n", cmd, arg);
+               printk("invalid ioctl: cmd = %x, arg = %lx\n", cmd, arg);
                return -ENOTTY;
        }
 }
index da661fb..1928220 100755 (executable)
@@ -37,8 +37,6 @@ eval 'sub OBD_IOC_GETATTR () { &_IOC(2, ord(\'f\'), 10, 4);}' unless
   defined(&OBD_IOC_GETATTR);
 eval 'sub OBD_IOC_READ () { &_IOC(3, ord(\'f\'), 11, 4);}' unless
   defined(&OBD_IOC_READ);
-eval 'sub OBD_IOC_READ2 () { &_IOC(3, ord(\'f\'), 17, 4);}' unless
-  defined(&OBD_IOC_READ2);
 eval 'sub OBD_IOC_WRITE () { &_IOC(3, ord(\'f\'), 12, 4);}' unless
   defined(&OBD_IOC_WRITE);
 eval 'sub OBD_IOC_CONNECT () { &_IOC(2, ord(\'f\'), 13, 4);}' unless
@@ -49,6 +47,14 @@ eval 'sub OBD_IOC_STATFS () { &_IOC(3, ord(\'f\'), 15, 4);}' unless
   defined(&OBD_IOC_STATFS);
 eval 'sub OBD_IOC_SYNC () { &_IOC(2, ord(\'f\'), 16, 4);}' unless
   defined(&OBD_IOC_SYNC);
+eval 'sub OBD_IOC_READ2 () { &_IOC(3, ord(\'f\'), 17, 4);}' unless
+  defined(&OBD_IOC_READ2);
+eval 'sub OBD_IOC_FORMATOBD () { &_IOC(3, ord(\'f\'), 18, 4);}' unless
+  defined(&OBD_IOC_FORMATOBD);
+eval 'sub OBD_IOC_PARTITION () { &_IOC(3, ord(\'f\'), 19, 4);}' unless
+  defined(&OBD_IOC_PARTITION);
+eval 'sub OBD_IOC_ATTACH () { &_IOC(3, ord(\'f\'), 20, 4);}' unless
+  defined(&OBD_IOC_ATTACH);
 
 eval 'sub ATTR_MODE () {1;}' unless defined(&ATTR_MODE);
 eval 'sub ATTR_UID () {2;}' unless defined(&ATTR_UID);
@@ -88,6 +94,9 @@ my $arg;
 
 my %commands =
     ('create' => {func => "Create", doc => "create: creates a new inode"},
+     'attach' => {func => "Attach", doc => "format type [adapter bus tid lun]"},
+     'format' => {func => "Format", doc => "format type adapter bus tid lun size"},
+     'partition' => {func => "Partition", doc => "partition type adapter bus tid lun partition size"},
      'setup' => {func => "Setup", doc => "setup: link the ext2 partition (default /dev/loop0) to this obddev"},
      'connect' => {func => "Connect", doc => "connect: allocates client ID for this session"},
      'disconnect' => {func => "Disconnect", doc => "disconnect [id]: frees client resources"},
@@ -173,10 +182,88 @@ sub execute_line {
     return (&{$commands{$cmd}->{func}}(@arg));
 }
 
+
+sub Attach {
+    my $err = 0;
+    my $type = shift;
+    my $data;
+    my $datalen = 0;
+
+    if ($type eq "obdscsi" ) {
+       my $adapter = shift;
+       my $bus = shift;
+       my $tid = shift;
+       my $lun = shift;
+       $data = pack("iiiii", $adapter, $bus, $tid, $lun, $size);
+       $datalen = 4 * 4;
+    }
+
+    my $packed = pack("ipip", length($type), $type, $datalen, $data);
+
+    my $rc = ioctl(DEV_OBD, &OBD_IOC_ATTACH, $packed);
+
+    if (!defined $rc) {
+       print STDERR "ioctl failed: $!\n";
+    } elsif ($rc eq "0 but true") {
+       print "Finished (success)\n";
+    } else {
+       print "ioctl returned error code $rc.\n";
+    }
+}
+
+sub Format {
+    my $err = 0;
+    my $size = shift;
+    my $data = pack("i", $size);
+    my $datalen = 4;
+
+    my $packed = pack("ip", $datalen, $data);
+    my $rc = ioctl(DEV_OBD, &OBD_IOC_FORMATOBD, $packed);
+
+    if (!defined $rc) {
+       print STDERR "ioctl failed: $!\n";
+    } elsif ($rc eq "0 but true") {
+       print "Finished (success)\n";
+    } else {
+       print "ioctl returned error code $rc.\n";
+    }
+}
+
+sub Partition {
+    my $err = 0;
+    my $partno = shift;
+    my $size = shift;
+    my $data = pack("ii", $partno, $size);
+    my $datalen = 2 * 4;
+
+    my $packed = pack("ip", $datalen, $data);
+    my $rc = ioctl(DEV_OBD, &OBD_IOC_PARTITION, $packed);
+
+    if (!defined $rc) {
+       print STDERR "ioctl failed: $!\n";
+    } elsif ($rc eq "0 but true") {
+       print "Finished (success)\n";
+    } else {
+       print "ioctl returned error code $rc.\n";
+    }
+}
+
 sub Setup {
     my $err = 0;
+    my $type = shift;
+    my $data;
+    my $datalen = 0;
     
-    my $packed = pack("La24", $::st->rdev(), "sim_obd");
+    $type = "sim_obd" unless $type;
+
+    if ( $type eq "sim_obd" ) {
+       my $dev = shift;
+       $dev = $::st->rdev() unless $dev;
+       $data = pack("i", $dev);
+       $datalen = 4;
+    }
+
+    my $packed = pack("ip", $datalen, $data);
     my $rc = ioctl(DEV_OBD, &OBD_IOC_SETUP_OBDDEV, $packed);
 
     if (!defined $rc) {
@@ -203,29 +290,17 @@ sub Cleanup {
 
 
 sub Connect {
-    my $id = 0;
-    my $ino = 0;
-    my $bs = 0;
-    my $bs_b = 0;
     my $rc;
 
-    # unsigned int conn_id;
-    # unsigned long conn_ino;
-    # unsigned long conn_blocksize;
-    # unsigned char conn_blocksize_bits;
-
-    my $packed = pack("ILLC", $id, $ino, $bs, $bs_b);
+    my $packed = "";
     $rc = ioctl(DEV_OBD, &OBD_IOC_CONNECT, $packed);
-    ($id, $ino, $bs, $bs_b) = unpack("ILLC", $packed);
+    $id = unpack("I", $packed);
 
     if (!defined $rc) {
        print STDERR "ioctl failed: $!\n";
     } elsif ($rc eq "0 but true") {
        $::client_id = $id;
        print "Client ID     : $id\n";
-       print "Root inode    : $ino\n";
-       print "Blocksize     : $bs\n";
-       print "Blocksize bits: $bs_b\n";
        print "Finished (success)\n";
     } else {
        print "ioctl returned error code $rc.\n";
index 7e87052..0c0fe1c 100644 (file)
@@ -89,13 +89,15 @@ int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
        struct page *page;
        struct inode *inode = filp->f_dentry->d_inode;
 
+       ENTRY;
+
        sb = inode->i_sb;
 
        stored = 0;
        offset = filp->f_pos & (PAGE_SIZE - 1);
 
        while (!error && !stored && filp->f_pos < inode->i_size) {
-               page = obdfs_getpage(inode, offset);
+               page = obdfs_getpage(inode, offset, 0, NOLOCK);
                if (!page) {
                        ext2_error (sb, "ext2_readdir",
                                    "directory #%lu contains a hole at offset %lu",
@@ -170,7 +172,9 @@ revalidate:
                        filp->f_pos += le16_to_cpu(de->rec_len);
                }
                offset = 0;
-               }
+               page_cache_release(page);
+       }
        UPDATE_ATIME(inode);
+       EXIT;
        return 0;
 }
index b6ba9c9..9738874 100644 (file)
@@ -34,6 +34,8 @@
 #include <linux/locks.h>
 #include <linux/quotaops.h>
 #include <linux/iobuf.h>
+
+#include <linux/obd_support.h>
 #include "obdfs.h"
 
 /*
@@ -86,7 +88,9 @@ struct page * obdfs_find_entry (struct inode * dir,
                struct ext2_dir_entry_2 * de;
                char * dlimit;
 
-               page = obdfs_getpage(dir, offset);
+               page = obdfs_getpage(dir, offset, 0, NOLOCK);
+               if ( !page ) 
+                       return NULL;
 
                de = (struct ext2_dir_entry_2 *) page_address(page);
                dlimit = (char *)page_address(page) + PAGE_SIZE; 
@@ -119,6 +123,7 @@ struct page * obdfs_find_entry (struct inode * dir,
        }
 
 failure:
+       page_cache_release(page);
        return NULL;
 }
 
@@ -146,7 +151,6 @@ struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry)
 }
 
 
-#if 0
 /*
  *     ext2_add_entry()
  *
@@ -156,15 +160,17 @@ struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry)
  * NOTE!! The inode part of 'de' is left at 0 - which means you
  * may not sleep between calling this and putting something into
  * the entry, as someone else might have used it while you slept.
+
+ * returns a locked page
  */
-static struct buffer_head * ext2_add_entry (struct inode * dir,
-                                           const char * name, int namelen,
-                                           struct ext2_dir_entry_2 ** res_dir,
-                                           int *err)
+static struct page *obdfs_add_entry (struct inode * dir,
+                                    const char * name, int namelen,
+                                    struct ext2_dir_entry_2 ** res_dir,
+                                    int *err)
 {
        unsigned long offset;
        unsigned short rec_len;
-       struct buffer_head * bh;
+       struct page *page;
        struct ext2_dir_entry_2 * de, * de1;
        struct super_block * sb;
 
@@ -184,19 +190,19 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                *err = -ENOENT;
                return NULL;
        }
-       bh = ext2_bread (dir, 0, 0, err);
-       if (!bh)
+       page = obdfs_getpage(dir, 0, 0, LOCKED);
+       if (!page)
                return NULL;
        rec_len = EXT2_DIR_REC_LEN(namelen);
        offset = 0;
-       de = (struct ext2_dir_entry_2 *) bh->b_data;
+       de = (struct ext2_dir_entry_2 *) page_address(page);
        *err = -ENOSPC;
        while (1) {
-               if ((char *)de >= sb->s_blocksize + bh->b_data) {
-                       brelse (bh);
-                       bh = NULL;
-                       bh = ext2_bread (dir, offset >> EXT2_BLOCK_SIZE_BITS(sb), 1, err);
-                       if (!bh)
+               if ((char *)de >= PAGE_SIZE + (char *)page_address(page)) {
+                       UnlockPage(page);
+                       page_cache_release(page);
+                       page = obdfs_getpage(dir, offset, 1, LOCKED);
+                       if (page)
                                return NULL;
                        if (dir->i_size <= offset) {
                                if (dir->i_size == 0) {
@@ -206,28 +212,31 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
 
                                ext2_debug ("creating next block\n");
 
-                               de = (struct ext2_dir_entry_2 *) bh->b_data;
+                               de = (struct ext2_dir_entry_2 *) page_address(page);
                                de->inode = 0;
                                de->rec_len = le16_to_cpu(sb->s_blocksize);
-                               dir->i_size = offset + sb->s_blocksize;
+                               dir->i_size = offset + PAGE_SIZE;
                                dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
                                mark_inode_dirty(dir);
                        } else {
 
                                ext2_debug ("skipping to next block\n");
 
-                               de = (struct ext2_dir_entry_2 *) bh->b_data;
+                               de = (struct ext2_dir_entry_2 *) page_address(page);
                        }
                }
+#if 0
                if (!ext2_check_dir_entry ("ext2_add_entry", dir, de, bh,
                                           offset)) {
                        *err = -ENOENT;
                        brelse (bh);
                        return NULL;
                }
+#endif
                if (ext2_match (namelen, name, de)) {
                                *err = -EEXIST;
-                               brelse (bh);
+                               UnlockPage(page);
+                               page_cache_release(page);
                                return NULL;
                }
                if ((le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) ||
@@ -260,15 +269,19 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                        dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
                        mark_inode_dirty(dir);
                        dir->i_version = ++event;
-                       mark_buffer_dirty(bh, 1);
                        *res_dir = de;
                        *err = 0;
-                       return bh;
+                       PDEBUG(page, "addentry");
+                       return page;
                }
                offset += le16_to_cpu(de->rec_len);
                de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        }
-       brelse (bh);
+
+       UnlockPage(page);
+       page_cache_release(page);
+       PDEBUG(page, "addentry");
+       EXIT;
        return NULL;
 }
 
@@ -276,19 +289,21 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
  * ext2_delete_entry deletes a directory entry by merging it with the
  * previous entry
  */
-static int ext2_delete_entry (struct ext2_dir_entry_2 * dir,
-                             struct buffer_head * bh)
+static int obdfs_delete_entry (struct ext2_dir_entry_2 * dir,
+                             struct page * page)
 {
        struct ext2_dir_entry_2 * de, * pde;
        int i;
 
        i = 0;
        pde = NULL;
-       de = (struct ext2_dir_entry_2 *) bh->b_data;
-       while (i < bh->b_size) {
+       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))
                        return -EIO;
+#endif
                if (de == dir)  {
                        if (pde)
                                pde->rec_len =
@@ -305,6 +320,7 @@ static int ext2_delete_entry (struct ext2_dir_entry_2 * dir,
        return -ENOENT;
 }
 
+
 static inline void ext2_set_de_type(struct super_block *sb,
                                struct ext2_dir_entry_2 *de,
                                umode_t mode) {
@@ -332,25 +348,33 @@ static inline void ext2_set_de_type(struct super_block *sb,
  * If the create succeeds, we fill in the inode information
  * with d_instantiate(). 
  */
-int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
+int obdfs_create (struct inode * dir, struct dentry * dentry, int mode)
 {
        struct inode * inode;
-       struct buffer_head * bh;
+       struct page *page;
        struct ext2_dir_entry_2 * de;
        int err = -EIO;
+       struct obdfs_sb_info *sbi;
+       ino_t ino;
 
+        ENTRY;
+
+       sbi = dir->i_sb->u.generic_sbp;
        /*
         * N.B. Several error exits in ext2_new_inode don't set err.
         */
-       inode = ext2_new_inode (dir, mode, &err);
+       ino = sbi->osi_ops->o_create(sbi->osi_obd, 0, &err);
+       if ( ino == -1 ) 
+               return -1;
+       inode =  iget(dir->i_sb, ino);
        if (!inode)
                return err;
 
-       inode->i_op = &ext2_file_inode_operations;
+       inode->i_op = &obdfs_inode_ops;
        inode->i_mode = mode;
        mark_inode_dirty(inode);
-       bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
-       if (!bh) {
+       page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
+       if (!page) {
                inode->i_nlink--;
                mark_inode_dirty(inode);
                iput (inode);
@@ -359,43 +383,64 @@ int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
        de->inode = cpu_to_le32(inode->i_ino);
        ext2_set_de_type(dir->i_sb, de, S_IFREG);
        dir->i_version = ++event;
-       mark_buffer_dirty(bh, 1);
+       sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
+                           dir->i_ino, page, 0);
+       UnlockPage(page);
+#if 0
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
        }
-       brelse (bh);
+#endif
+       page_cache_release(page);
        d_instantiate(dentry, inode);
        return 0;
 }
 
-int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
+int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
 {
        struct inode * inode;
-       struct buffer_head * bh;
+       struct page *page;
        struct ext2_dir_entry_2 * de;
        int err = -EIO;
+       struct obdfs_sb_info *sbi;
 
-       inode = ext2_new_inode (dir, mode, &err);
+       ino_t ino;
+
+        ENTRY;
+
+       sbi = dir->i_sb->u.generic_sbp;
+       /*
+        * N.B. Several error exits in ext2_new_inode don't set err.
+        */
+       ino = sbi->osi_ops->o_create(sbi->osi_obd, 0, &err);
+       if ( ino == -1 ) 
+               return -1;
+       inode =  iget(dir->i_sb, ino);
        if (!inode)
-               goto out;
+               return err;
 
        inode->i_uid = current->fsuid;
        init_special_inode(inode, mode, rdev);
-       bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
-       if (!bh)
+       page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
+       if (!page)
                goto out_no_entry;
        de->inode = cpu_to_le32(inode->i_ino);
        dir->i_version = ++event;
        ext2_set_de_type(dir->i_sb, de, inode->i_mode);
        mark_inode_dirty(inode);
-       mark_buffer_dirty(bh, 1);
+       sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
+                           dir->i_ino, page, 0);
+       UnlockPage(page);
+
+#if 0
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
        }
+#endif
        d_instantiate(dentry, inode);
-       brelse(bh);
+       page_cache_release(page);
        err = 0;
 out:
        return err;
@@ -407,114 +452,140 @@ out_no_entry:
        goto out;
 }
 
-int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
+int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 {
-       struct inode * inode;
-       struct buffer_head * bh, * dir_block;
+       struct inode * child;
+       struct page *page, *child_page;
        struct ext2_dir_entry_2 * de;
+       struct obdfs_sb_info *sbi;
        int err;
+       ino_t ino;
+
+       ENTRY;
+       sbi = dir->i_sb->u.generic_sbp;
 
        err = -EMLINK;
        if (dir->i_nlink >= EXT2_LINK_MAX)
                goto out;
 
        err = -EIO;
-       inode = ext2_new_inode (dir, S_IFDIR, &err);
-       if (!inode)
-               goto out;
+       ino = iops(dir)->o_create(sbi->osi_obd, 0, &err);
+       if ( ino == -1 ) 
+               return -1;
+       child =  iget(dir->i_sb, ino);
+       if (!child)
+               return err;
 
-       inode->i_op = &ext2_dir_inode_operations;
-       inode->i_size = inode->i_sb->s_blocksize;
-       inode->i_blocks = 0;    
-       dir_block = ext2_bread (inode, 0, 1, &err);
-       if (!dir_block) {
-               inode->i_nlink--; /* is this nlink == 0? */
-               mark_inode_dirty(inode);
-               iput (inode);
+
+       child->i_op = &obdfs_inode_ops;
+       child->i_size = PAGE_SIZE;
+       child->i_blocks = 0;    
+       child_page = obdfs_getpage(child, 0, 1, LOCKED);
+       if (!child_page) {
+               child->i_nlink--; /* is this nlink == 0? */
+               mark_inode_dirty(child);
+               iput (child);
                return err;
        }
-       de = (struct ext2_dir_entry_2 *) dir_block->b_data;
-       de->inode = cpu_to_le32(inode->i_ino);
+       child->i_blocks = PAGE_SIZE/child->i_sb->s_blocksize;
+
+       /* create . and .. */
+       de = (struct ext2_dir_entry_2 *) page_address(child_page);
+       de->inode = cpu_to_le32(child->i_ino);
        de->name_len = 1;
        de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
        strcpy (de->name, ".");
        ext2_set_de_type(dir->i_sb, de, S_IFDIR);
+       
        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(inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1));
+       de->rec_len = cpu_to_le16(child->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1));
        de->name_len = 2;
        strcpy (de->name, "..");
        ext2_set_de_type(dir->i_sb, de, S_IFDIR);
-       inode->i_nlink = 2;
-       mark_buffer_dirty(dir_block, 1);
-       brelse (dir_block);
-       inode->i_mode = S_IFDIR | mode;
+       
+       iops(dir)->o_brw(WRITE, sbi->osi_conn_info.conn_id, child->i_ino, child_page, 1);
+       UnlockPage(child_page);
+       page_cache_release(child_page);
+
+       child->i_nlink = 2;
+       child->i_mode = S_IFDIR | mode;
        if (dir->i_mode & S_ISGID)
-               inode->i_mode |= S_ISGID;
-       mark_inode_dirty(inode);
-       bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
-       if (!bh)
+               child->i_mode |= S_ISGID;
+       mark_inode_dirty(child);
+
+       /* now deal with the parent */
+       page = obdfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
+       if (!page) {
                goto out_no_entry;
-       de->inode = cpu_to_le32(inode->i_ino);
+       }
+
+       de->inode = cpu_to_le32(child->i_ino);
        ext2_set_de_type(dir->i_sb, de, S_IFDIR);
        dir->i_version = ++event;
-       mark_buffer_dirty(bh, 1);
+
+#if 0
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
        }
+#endif
        dir->i_nlink++;
        dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(dir);
-       d_instantiate(dentry, inode);
-       brelse (bh);
+       iops(dir)->o_brw(WRITE, sbi->osi_conn_info.conn_id, dir->i_ino, page, 1);
+       UnlockPage(page);
+       page_cache_release(page);
+       d_instantiate(dentry, child);
        err = 0;
 out:
+       EXIT;
        return err;
 
 out_no_entry:
-       inode->i_nlink = 0;
-       mark_inode_dirty(inode);
-       iput (inode);
+       child->i_nlink = 0;
+       mark_inode_dirty(child);
+       iput (child);
        goto out;
 }
 
+
 /*
  * routine to check that the specified directory is empty (for rmdir)
  */
 static int empty_dir (struct inode * inode)
 {
        unsigned long offset;
-       struct buffer_head * bh;
+       struct page *page;
        struct ext2_dir_entry_2 * de, * de1;
        struct super_block * sb;
-       int err;
 
        sb = inode->i_sb;
        if (inode->i_size < EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) ||
-           !(bh = ext2_bread (inode, 0, 0, &err))) {
+           !(page = obdfs_getpage (inode, 0, 0, NOLOCK))) {
                ext2_warning (inode->i_sb, "empty_dir",
                              "bad directory (dir #%lu) - no data block",
                              inode->i_ino);
                return 1;
        }
-       de = (struct ext2_dir_entry_2 *) bh->b_data;
+       de = (struct ext2_dir_entry_2 *) page_address(page);
        de1 = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        if (le32_to_cpu(de->inode) != inode->i_ino || !le32_to_cpu(de1->inode) || 
            strcmp (".", de->name) || strcmp ("..", de1->name)) {
                ext2_warning (inode->i_sb, "empty_dir",
                              "bad directory (dir #%lu) - no `.' or `..'",
                              inode->i_ino);
-               brelse (bh);
+               page_cache_release(page);
                return 1;
        }
        offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
        de = (struct ext2_dir_entry_2 *) ((char *) de1 + le16_to_cpu(de1->rec_len));
        while (offset < inode->i_size ) {
-               if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
-                       brelse (bh);
-                       bh = ext2_bread (inode, offset >> EXT2_BLOCK_SIZE_BITS(sb), 0, &err);
-                       if (!bh) {
+               if (!page || (void *) de >= (void *) (page_address(page) + PAGE_SIZE)) {
+                       if (page) 
+                               page_cache_release(page);
+                       page = obdfs_getpage(inode, offset, 0, NOLOCK);
+                       if (!page) {
 #if 0
                                ext2_error (sb, "empty_dir",
                                            "directory #%lu contains a hole at offset %lu",
@@ -523,34 +594,40 @@ static int empty_dir (struct inode * inode)
                                offset += sb->s_blocksize;
                                continue;
                        }
-                       de = (struct ext2_dir_entry_2 *) bh->b_data;
+                       de = (struct ext2_dir_entry_2 *) page_address(page);
                }
+#if 0
                if (!ext2_check_dir_entry ("empty_dir", inode, de, bh,
                                           offset)) {
                        brelse (bh);
                        return 1;
                }
+#endif
                if (le32_to_cpu(de->inode)) {
-                       brelse (bh);
+                       page_cache_release(page);
                        return 0;
                }
                offset += le16_to_cpu(de->rec_len);
                de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        }
-       brelse (bh);
+       page_cache_release(page);
        return 1;
 }
 
-int ext2_rmdir (struct inode * dir, struct dentry *dentry)
+int obdfs_rmdir (struct inode * dir, struct dentry *dentry)
 {
        int retval;
        struct inode * inode;
-       struct buffer_head * bh;
+       struct page *page;
        struct ext2_dir_entry_2 * de;
+       struct obdfs_sb_info *sbi;
+
+        ENTRY;
+       sbi = dir->i_sb->u.generic_sbp;
 
        retval = -ENOENT;
-       bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
-       if (!bh)
+       page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
+       if (!page)
                goto end_rmdir;
 
        inode = dentry->d_inode;
@@ -564,15 +641,19 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry)
        if (!empty_dir (inode))
                goto end_rmdir;
 
-       retval = ext2_delete_entry (de, bh);
+       retval = obdfs_delete_entry (de, page);
        dir->i_version = ++event;
        if (retval)
                goto end_rmdir;
-       mark_buffer_dirty(bh, 1);
+       sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
+                           dir->i_ino, page, 0);
+       UnlockPage(page);
+#if 0
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
        }
+#endif
        if (inode->i_nlink != 2)
                ext2_warning (inode->i_sb, "ext2_rmdir",
                              "empty directory has nlink!=2 (%d)",
@@ -588,20 +669,25 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry)
        d_delete(dentry);
 
 end_rmdir:
-       brelse (bh);
+       if ( page )
+               page_cache_release(page);
        return retval;
 }
 
-int ext2_unlink(struct inode * dir, struct dentry *dentry)
+int obdfs_unlink(struct inode * dir, struct dentry *dentry)
 {
        int retval;
        struct inode * inode;
-       struct buffer_head * bh;
+       struct page *page;
        struct ext2_dir_entry_2 * de;
+       struct obdfs_sb_info *sbi;
+
+        ENTRY;
+       sbi = dir->i_sb->u.generic_sbp;
 
        retval = -ENOENT;
-       bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
-       if (!bh)
+       page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
+       if (!page)
                goto end_unlink;
 
        inode = dentry->d_inode;
@@ -617,15 +703,19 @@ int ext2_unlink(struct inode * dir, struct dentry *dentry)
                              inode->i_ino, inode->i_nlink);
                inode->i_nlink = 1;
        }
-       retval = ext2_delete_entry (de, bh);
+       retval = obdfs_delete_entry (de, page);
        if (retval)
                goto end_unlink;
        dir->i_version = ++event;
-       mark_buffer_dirty(bh, 1);
+       sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
+                           dir->i_ino, page, 0);
+       UnlockPage(page);
+#if 0
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
        }
+#endif
        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(dir);
@@ -636,24 +726,37 @@ int ext2_unlink(struct inode * dir, struct dentry *dentry)
        d_delete(dentry);       /* This also frees the inode */
 
 end_unlink:
-       brelse (bh);
+       if (page)
+               page_cache_release(page);
        return retval;
 }
 
-int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symname)
+int obdfs_symlink (struct inode * dir, struct dentry *dentry, const char * symname)
 {
        struct ext2_dir_entry_2 * de;
        struct inode * inode;
-       struct buffer_head * bh = NULL, * name_block = NULL;
+       struct page* page = NULL, * name_page = NULL;
        char * link;
        int i, l, err = -EIO;
        char c;
+       struct obdfs_sb_info *sbi;
+       ino_t ino;
+
+        ENTRY;
 
-       if (!(inode = ext2_new_inode (dir, S_IFLNK, &err))) {
+       sbi = dir->i_sb->u.generic_sbp;
+       /*
+        * N.B. Several error exits in ext2_new_inode don't set err.
+        */
+       ino = sbi->osi_ops->o_create(sbi->osi_obd, 0, &err);
+       if ( ino == -1 ) 
+               return -1;
+       inode =  iget(dir->i_sb, ino);
+       if (!inode)
                return err;
-       }
+
        inode->i_mode = S_IFLNK | S_IRWXUGO;
-       inode->i_op = &ext2_symlink_inode_operations;
+       inode->i_op = &obdfs_inode_ops;
        for (l = 0; l < inode->i_sb->s_blocksize - 1 &&
             symname [l]; l++)
                ;
@@ -661,14 +764,14 @@ int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symnam
 
                ext2_debug ("l=%d, normal symlink\n", l);
 
-               name_block = ext2_bread (inode, 0, 1, &err);
-               if (!name_block) {
+               name_page = obdfs_getpage(inode, 0, 1, LOCKED);
+               if (!name_page) {
                        inode->i_nlink--;
                        mark_inode_dirty(inode);
                        iput (inode);
                        return err;
                }
-               link = name_block->b_data;
+               link = (char *)page_address(name_page);
        } else {
                link = (char *) inode->u.ext2_i.i_data;
 
@@ -679,25 +782,31 @@ int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symnam
        while (i < inode->i_sb->s_blocksize - 1 && (c = *(symname++)))
                link[i++] = c;
        link[i] = 0;
-       if (name_block) {
-               mark_buffer_dirty(name_block, 1);
-               brelse (name_block);
+       if (name_page) {
+               sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
+                                   inode->i_ino, name_page, 1);
+               PDEBUG(name_page, "symlink");
+               UnlockPage(name_page);
+               page_cache_release(name_page);
        }
        inode->i_size = i;
        mark_inode_dirty(inode);
 
-       bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
-       if (!bh)
+       page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
+       if (!page)
                goto out_no_entry;
        de->inode = cpu_to_le32(inode->i_ino);
        ext2_set_de_type(dir->i_sb, de, S_IFLNK);
        dir->i_version = ++event;
-       mark_buffer_dirty(bh, 1);
+       sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
+                           dir->i_ino, page, 1);
+       UnlockPage(page);
+#if 0
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
        }
-       brelse (bh);
+#endif
        d_instantiate(dentry, inode);
        err = 0;
 out:
@@ -710,13 +819,17 @@ out_no_entry:
        goto out;
 }
 
-int ext2_link (struct dentry * old_dentry,
+int obdfs_link (struct dentry * old_dentry,
                struct inode * dir, struct dentry *dentry)
 {
        struct inode *inode = old_dentry->d_inode;
        struct ext2_dir_entry_2 * de;
-       struct buffer_head * bh;
+       struct page *page;
        int err;
+       struct obdfs_sb_info *sbi;
+
+        ENTRY;
+       sbi = dir->i_sb->u.generic_sbp;
 
        if (S_ISDIR(inode->i_mode))
                return -EPERM;
@@ -724,19 +837,24 @@ int ext2_link (struct dentry * old_dentry,
        if (inode->i_nlink >= EXT2_LINK_MAX)
                return -EMLINK;
 
-       bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
-       if (!bh)
+       page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
+       if (!page)
                return err;
 
        de->inode = cpu_to_le32(inode->i_ino);
        ext2_set_de_type(dir->i_sb, de, inode->i_mode);
        dir->i_version = ++event;
-       mark_buffer_dirty(bh, 1);
+       sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
+                           dir->i_ino, page, 0);
+       UnlockPage(page);
+
+#if 0
        if (IS_SYNC(dir)) {
                ll_rw_block (WRITE, 1, &bh);
                wait_on_buffer (bh);
        }
-       brelse (bh);
+#endif
+       page_cache_release(page);
        inode->i_nlink++;
        inode->i_ctime = CURRENT_TIME;
        mark_inode_dirty(inode);
@@ -753,17 +871,21 @@ int ext2_link (struct dentry * old_dentry,
  * Anybody can rename anything with this: the permission checks are left to the
  * higher-level routines.
  */
-int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
+int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry,
                           struct inode * new_dir,struct dentry *new_dentry)
 {
        struct inode * old_inode, * new_inode;
-       struct buffer_head * old_bh, * new_bh, * dir_bh;
+       struct page * old_page, * new_page, * dir_page;
        struct ext2_dir_entry_2 * old_de, * new_de;
        int retval;
+       struct obdfs_sb_info *sbi;
+
+        ENTRY;
+       sbi = old_dir->i_sb->u.generic_sbp;
 
-       old_bh = new_bh = dir_bh = NULL;
+       new_page = dir_page = NULL;
 
-       old_bh = ext2_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de);
+       old_page = obdfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de);
        /*
         *  Check for inode number is _not_ due to possible IO errors.
         *  We might rmdir the source, keep it as pwd of some process
@@ -772,16 +894,16 @@ int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
         */
        old_inode = old_dentry->d_inode;
        retval = -ENOENT;
-       if (!old_bh || le32_to_cpu(old_de->inode) != old_inode->i_ino)
+       if (!old_page || le32_to_cpu(old_de->inode) != old_inode->i_ino)
                goto end_rename;
 
        new_inode = new_dentry->d_inode;
-       new_bh = ext2_find_entry (new_dir, new_dentry->d_name.name,
+       new_page = obdfs_find_entry (new_dir, new_dentry->d_name.name,
                                new_dentry->d_name.len, &new_de);
-       if (new_bh) {
+       if (new_page) {
                if (!new_inode) {
-                       brelse (new_bh);
-                       new_bh = NULL;
+                       page_cache_release(new_page);
+                       new_page = NULL;
                } else {
                        DQUOT_INIT(new_inode);
                }
@@ -793,21 +915,21 @@ int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
                                goto end_rename;
                }
                retval = -EIO;
-               dir_bh = ext2_bread (old_inode, 0, 0, &retval);
-               if (!dir_bh)
+               dir_page= obdfs_getpage (old_inode, 0, 0, LOCKED);
+               if (!dir_page)
                        goto end_rename;
-               if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
+               if (le32_to_cpu(PARENT_INO(page_address(dir_page))) != old_dir->i_ino)
                        goto end_rename;
                retval = -EMLINK;
                if (!new_inode && new_dir!=old_dir &&
                                new_dir->i_nlink >= EXT2_LINK_MAX)
                        goto end_rename;
        }
-       if (!new_bh) {
-               new_bh = ext2_add_entry (new_dir, new_dentry->d_name.name,
+       if (!new_page) {
+               new_page = obdfs_add_entry (new_dir, new_dentry->d_name.name,
                                        new_dentry->d_name.len, &new_de,
                                        &retval);
-               if (!new_bh)
+               if (!new_page)
                        goto end_rename;
        }
        new_dir->i_version = ++event;
@@ -820,7 +942,7 @@ int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
                                      EXT2_FEATURE_INCOMPAT_FILETYPE))
                new_de->file_type = old_de->file_type;
        
-       ext2_delete_entry (old_de, old_bh);
+       obdfs_delete_entry (old_de, old_page);
 
        old_dir->i_version = ++event;
        if (new_inode) {
@@ -831,9 +953,10 @@ int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
        old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
        old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
        mark_inode_dirty(old_dir);
-       if (dir_bh) {
-               PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
-               mark_buffer_dirty(dir_bh, 1);
+       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_dir->i_nlink--;
                mark_inode_dirty(old_dir);
                if (new_inode) {
@@ -845,23 +968,31 @@ int ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
                        mark_inode_dirty(new_dir);
                }
        }
-       mark_buffer_dirty(old_bh,  1);
+       sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
+                           old_inode->i_ino, old_page, 0);
+#if 0
        if (IS_SYNC(old_dir)) {
                ll_rw_block (WRITE, 1, &old_bh);
                wait_on_buffer (old_bh);
        }
-       mark_buffer_dirty(new_bh, 1);
+#endif
+       sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
+                           new_inode->i_ino, new_page, 0);
+#if 0
        if (IS_SYNC(new_dir)) {
                ll_rw_block (WRITE, 1, &new_bh);
                wait_on_buffer (new_bh);
        }
+#endif
 
        retval = 0;
 
 end_rename:
-       brelse (dir_bh);
-       brelse (old_bh);
-       brelse (new_bh);
+       if (old_page)
+               page_cache_release(old_page);
+       if (new_page)
+               page_cache_release(new_page);
+       if (dir_page)
+               page_cache_release(dir_page);
        return retval;
 }
-#endif
index 389058c..ff06852 100644 (file)
@@ -45,14 +45,14 @@ int obdfs_readpage(struct file *file, struct page *page)
 
        /* XXX flush stuff */
        sbi = sb->u.generic_sbp;
-       PDEBUG(page, READ);
+       PDEBUG(page, "READ");
        rc =  sbi->osi_ops->o_brw(READ, sbi->osi_conn_info.conn_id, 
-                     file->f_dentry->d_inode->i_ino, page);
+                     file->f_dentry->d_inode->i_ino, page, 0);
        if (rc == PAGE_SIZE ) {
                SetPageUptodate(page);
                UnlockPage(page);
        } 
-       PDEBUG(page, READ);
+       PDEBUG(page, "READ");
        if ( rc == PAGE_SIZE ) 
                rc = 0;
        return rc;
@@ -71,10 +71,22 @@ int obdfs_readpage(struct file *file, struct page *page)
 int obdfs_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
 {
        long status;
-
+        struct obdfs_sb_info *sbi = file->f_dentry->d_inode->i_sb->u.generic_sbp;
+
+       if ( !Page_Uptodate(page) ) {
+               status =  sbi->osi_ops->o_brw(READ, 
+                                             sbi->osi_conn_info.conn_id, 
+                                             file->f_dentry->d_inode->i_ino, 
+                                             page, 1);
+               if (status == PAGE_SIZE ) {
+                       SetPageUptodate(page);
+               } else { 
+                       return status;
+               }
+       }
        bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes);
        status = -EFAULT;
-       CDEBUG(D_INODE, "page offset %ld, bytes %ld, offset %ld, page addr %lx, writing: %s, beg of page %s\n", page->offset, bytes, offset, page_address(page), ((char *) page_address(page)) + offset, (char *)page_address(page));
+
        if (bytes) {
                lock_kernel();
                status = obdfs_writepage(file, page);
@@ -92,19 +104,17 @@ int obdfs_write_one_page(struct file *file, struct page *page, unsigned long off
 /* returns the page unlocked, but with a reference */
 int obdfs_writepage(struct file *file, struct page *page)
 {
-        struct obdfs_sb_info *sbi;
-       struct super_block *sb = file->f_dentry->d_inode->i_sb;
+        struct obdfs_sb_info *sbi = file->f_dentry->d_inode->i_sb->u.generic_sbp;
        int rc;
 
         ENTRY;
-       PDEBUG(page,WRITE);
+       PDEBUG(page, "WRITEPAGE");
        /* XXX flush stuff */
-       sbi = sb->u.generic_sbp;
 
        rc = sbi->osi_ops->o_brw(WRITE, sbi->osi_conn_info.conn_id, 
-                     file->f_dentry->d_inode->i_ino, page);
+                     file->f_dentry->d_inode->i_ino, page, 1);
        SetPageUptodate(page);
-       PDEBUG(page,WRITE);
+       PDEBUG(page,"WRITEPAGE");
        return rc;
 }
 
@@ -113,7 +123,7 @@ int obdfs_writepage(struct file *file, struct page *page)
    page is returned unlocked, with the up to date flag set, 
    and held, i.e. caller must do a page_put
 */
-struct page *obdfs_getpage(struct inode *inode, unsigned long offset)
+struct page *obdfs_getpage(struct inode *inode, unsigned long offset, int create, int locked)
 {
        unsigned long new_page;
        struct page ** hash;
@@ -125,9 +135,11 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset)
 
        sbi = sb->u.generic_sbp;
        
-       page = find_get_page(inode, offset); 
+       page = find_lock_page(inode, offset); 
        if (page && Page_Uptodate(page)) { 
-               PDEBUG(page,READ);
+               PDEBUG(page,"GETPAGE");
+               if (!locked)
+                       UnlockPage(page);
                return page;
        } 
                
@@ -143,13 +155,16 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset)
        /* 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,READ);
+               PDEBUG(page,"GETPAGE");
                sbi->osi_ops->o_brw(READ, sbi->osi_conn_info.conn_id, 
-                                   inode->i_ino, page);
-               UnlockPage(page);
+                                   inode->i_ino, page, create);
+               if ( !locked )
+                       UnlockPage(page);
                SetPageUptodate(page);
+               PDEBUG(page,"GETPAGE");
                return page;
        }
        /*
@@ -157,13 +172,13 @@ struct page *obdfs_getpage(struct inode *inode, unsigned long offset)
         * raced with us and added our page to the cache first.
         */
        CDEBUG(D_INODE, "Page not found. Someone raced us.\n");
-       PDEBUG(page,READ);
+       PDEBUG(page,"GETPAGE");
        return page;
 }
 
 
 
-struct file_operations obdfs_file_operations = {
+struct file_operations obdfs_file_ops = {
        NULL,                   /* lseek - default */
        generic_file_read,      /* read */
        obdfs_file_write,     /* write - bad */
@@ -181,16 +196,16 @@ struct file_operations obdfs_file_operations = {
 };
 
 struct inode_operations obdfs_inode_ops = {
-       &obdfs_file_operations, /* default directory file-ops */
-       NULL,           /* create */
+       &obdfs_file_ops,        /* default directory file-ops */
+       obdfs_create,   /* create */
        obdfs_lookup,   /* lookup */
-       NULL,           /* link */
-       NULL,           /* unlink */
-       NULL,           /* symlink */
-       NULL,           /* mkdir */
-       NULL,           /* rmdir */
-       NULL,           /* mknod */
-       NULL,           /* rename */
+       obdfs_link,     /* link */
+       obdfs_unlink,   /* unlink */
+       obdfs_symlink,  /* symlink */
+       obdfs_mkdir,    /* mkdir */
+       obdfs_rmdir,    /* rmdir */
+       obdfs_mknod,    /* mknod */
+       obdfs_rename,   /* rename */
        NULL,           /* readlink */
        NULL,           /* follow_link */
        NULL,           /* get_block */
index c40122b..0072f36 100644 (file)
@@ -67,6 +67,11 @@ static struct super_block * obdfs_read_super(struct super_block *sb,
         struct inode *root = 0; 
        struct obdfs_sb_info *sbi = NULL;
         int error = 0;
+       unsigned long blocksize;
+       unsigned long blocksize_bits;
+       unsigned long root_ino;
+       int scratch;
+       
 
        ENTRY;
         MOD_INC_USE_COUNT; 
@@ -82,7 +87,7 @@ static struct super_block * obdfs_read_super(struct super_block *sb,
        sbi->osi_obd = &obd_dev[obd_minor];
        sbi->osi_ops = sbi->osi_obd->obd_type->typ_ops;
        
-        error  = sbi->osi_ops->o_connect(obd_minor, &sbi->osi_conn_info);
+        error  = sbi->osi_ops->o_connect(sbi->osi_obd, &sbi->osi_conn_info);
        if ( error ) {
                printk("OBDFS: cannot connect to 0x%x.\n", obd_minor);
                goto error;
@@ -90,15 +95,44 @@ static struct super_block * obdfs_read_super(struct super_block *sb,
 
        sbi->osi_super = sb;
 
+       error = sbi->osi_ops->o_get_info(sbi->osi_conn_info.conn_id, 
+                                        strlen("blocksize"), 
+                                        "blocksize", 
+                                        &scratch, (void *)&blocksize);
+       if ( error ) {
+               printk("Getinfo call to drive failed (blocksize)\n");
+               goto error;
+       }
+
+       error = sbi->osi_ops->o_get_info(sbi->osi_conn_info.conn_id, 
+                                        strlen("blocksize_bits"), 
+                                        "blocksize_bits", 
+                                        &scratch, (void *)&blocksize_bits);
+       if ( error ) {
+               printk("Getinfo call to drive failed (blocksize_bits)\n");
+               goto error;
+       }
+
+       error = sbi->osi_ops->o_get_info(sbi->osi_conn_info.conn_id, 
+                                        strlen("root_ino"), 
+                                        "root_ino", 
+                                        &scratch, (void *)&root_ino);
+       if ( error ) {
+               printk("Getinfo call to drive failed (root_ino)\n");
+               goto error;
+       }
+       
+
         lock_super(sb);
         sb->u.generic_sbp = sbi;
-        sb->s_blocksize = sbi->osi_conn_info.conn_blocksize;
-        sb->s_blocksize_bits = sbi->osi_conn_info.conn_blocksize_bits;
+       
+        sb->s_blocksize = blocksize;
+        sb->s_blocksize_bits = (unsigned char)blocksize_bits;
         sb->s_magic = OBDFS_SUPER_MAGIC;
         sb->s_op = &obdfs_super_operations;
 
        /* make root inode */
-       root = iget(sb, sbi->osi_conn_info.conn_ino);
+       root = iget(sb, root_ino);
         if (!root || is_bad_inode(root)) {
            printk("OBDFS: bad iget for root\n");
            sb->s_dev = 0;
@@ -155,47 +189,29 @@ extern struct inode_operations obdfs_inode_ops;
 /* all filling in of inodes postponed until lookup */
 static void obdfs_read_inode(struct inode *inode)
 {
-       struct iattr attr;
        int error;
        struct obdfs_sb_info *sbi = inode->i_sb->u.generic_sbp;
        ENTRY;
 
        error = sbi->osi_ops->o_getattr(sbi->osi_conn_info.conn_id, 
-                                       inode->i_ino, &attr);
+                                       inode->i_ino, inode);
        if (error) {
                printk("obdfs_read_inode: ibd_getattr fails (%d)\n", error);
                return;
        }
 
-       inode_setattr(inode, &attr);
        inode->i_op = &obdfs_inode_ops;
        return;
 }
 
-static void inode_to_iattr(struct inode *inode, struct iattr *tmp)
-{
-       tmp->ia_mode = inode->i_mode;
-       tmp->ia_uid = inode->i_uid;
-       tmp->ia_gid = inode->i_gid;
-       tmp->ia_size = inode->i_size;
-       tmp->ia_atime = inode->i_atime;
-       tmp->ia_mtime = inode->i_mtime;
-       tmp->ia_ctime = inode->i_ctime;
-       tmp->ia_attr_flags = inode->i_flags;
-
-       tmp->ia_valid = ~0;
-}
-
 static void obdfs_write_inode(struct inode *inode) 
 {
         struct obdfs_sb_info *sbi;
-       struct iattr attr;
        int error;
        
-       inode_to_iattr(inode, &attr);
        sbi = inode->i_sb->u.generic_sbp;
        error = sbi->osi_ops->o_setattr(sbi->osi_conn_info.conn_id, 
-                                       inode->i_ino, &attr);
+                                       inode->i_ino, inode);
        if (error) {
                printk("obdfs_write_inode: ibd_setattr fails (%d)\n", error);
                return;
@@ -224,19 +240,21 @@ static void obdfs_delete_inode(struct inode *inode)
 static int  obdfs_notify_change(struct dentry *de, struct iattr *iattr)
 {
        struct inode *inode = de->d_inode;
+       struct iattr saved_copy;
        struct obdfs_sb_info * sbi;
        int error;
 
        ENTRY;
+       inode_to_iattr(inode, &saved_copy);
 
        sbi = inode->i_sb->u.generic_sbp;
+       inode_setattr(inode, iattr);
         error = sbi->osi_ops->o_setattr(sbi->osi_conn_info.conn_id, 
-                                       inode->i_ino, iattr);
+                                       inode->i_ino, inode);
        if ( error ) {
+               inode_setattr(inode, &saved_copy);
                printk("obdfs_notify_change: obd_setattr fails (%d)\n", error);
                return error;
-       } else {
-               inode_setattr(inode, iattr);
        }
        EXIT;
         return error;
@@ -276,7 +294,7 @@ int init_obdfs(void)
        obdfs_sysctl_init();
 
        obd_sbi = &obdfs_super_info;
-       obd_fso = &obdfs_file_operations;
+       obd_fso = &obdfs_file_ops;
 
        return register_filesystem(&obdfs_fs_type);
 }