/* * OBDFS Super operations * * Copryright (C) 1996 Peter J. Braam */ #define EXPORT_SYMTAB #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include <../obd/linux/sim_obd.h> #include /* VFS super_block ops */ static struct super_block *obdfs_read_super(struct super_block *, void *, int); static void obdfs_read_inode(struct inode *); static int obdfs_notify_change(struct dentry *dentry, struct iattr *attr); static void obdfs_write_inode(struct inode *); static void obdfs_delete_inode(struct inode *); static void obdfs_put_super(struct super_block *); static int obdfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); /* exported operations */ struct super_operations obdfs_super_operations = { obdfs_read_inode, /* read_inode */ obdfs_write_inode, /* write_inode */ NULL, /* put_inode */ obdfs_delete_inode, /* delete_inode */ obdfs_notify_change, /* notify_change */ obdfs_put_super, /* put_super */ NULL, /* write_super */ obdfs_statfs, /* statfs */ NULL /* remount_fs */ }; struct obdfs_sb_info obdfs_super_info; int obd_minor = 0; int obd_root_ino = 2; static struct super_block * obdfs_read_super(struct super_block *sb, void *data, int silent) { struct inode *root = 0; struct obdfs_sb_info *sbi = NULL; int error = 0; ENTRY; MOD_INC_USE_COUNT; sbi = &obdfs_super_info; if ( sbi->osi_super ) { printk("Already mounted\n"); MOD_DEC_USE_COUNT; return NULL; } error = obd_connect(obd_minor, &sbi->osi_conn_info); if ( error ) { printk("OBDFS: cannot connect to 0x%x.\n", obd_minor); goto error; } sbi->osi_super = sb; 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_magic = OBDFS_SUPER_MAGIC; sb->s_op = &obdfs_super_operations; /* make root inode */ root = iget(sb, sbi->osi_conn_info.conn_ino); if (!root || is_bad_inode(root)) { printk("OBDFS: bad iget for root\n"); sb->s_dev = 0; error = ENOENT; unlock_super(sb); goto error; } printk("obdfs_read_super: rootinode is %ld dev %d\n", root->i_ino, root->i_dev); sb->s_root = d_alloc_root(root, NULL); unlock_super(sb); EXIT; return sb; error: EXIT; MOD_DEC_USE_COUNT; if (sbi) { sbi->osi_super = NULL; } if (root) { iput(root); } sb->s_dev = 0; return NULL; } static void obdfs_put_super(struct super_block *sb) { struct obdfs_sb_info *sbi; ENTRY; sb->s_dev = 0; /* XXX flush stuff */ sbi = sb->u.generic_sbp; sb->u.generic_sbp = NULL; obd_disconnect(sbi->osi_conn_info.conn_id); sbi->osi_super = NULL; printk("OBDFS: Bye bye.\n"); memset(sbi, 0, sizeof(* sbi)); MOD_DEC_USE_COUNT; EXIT; } /* 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 = obd_getattr(sbi->osi_conn_info.conn_id, inode->i_ino, &attr); if (error) { printk("obdfs_read_inode: ibd_getattr fails (%d)\n", error); return; } inode_setattr(inode, &attr); inode->i_op = NULL; 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; ENTRY; inode_to_iattr(inode, &attr); sbi = inode->i_sb->u.generic_sbp; error = obd_setattr(sbi->osi_conn_info.conn_id, inode->i_ino, &attr); if (error) { printk("obdfs_write_inode: ibd_setattr fails (%d)\n", error); return; } return; } static void obdfs_delete_inode(struct inode *inode) { struct obdfs_sb_info *sbi; int error; ENTRY; sbi = inode->i_sb->u.generic_sbp; error = obd_destroy(sbi->osi_conn_info.conn_id , inode->i_ino); if (error) { printk("obdfs_delete_node: ibd_destroy fails (%d)\n", error); return; } EXIT; } static int obdfs_notify_change(struct dentry *de, struct iattr *iattr) { struct inode *inode = de->d_inode; struct obdfs_sb_info * sbi; int error; ENTRY; sbi = inode->i_sb->u.generic_sbp; error = obd_setattr(sbi->osi_conn_info.conn_id, inode->i_ino, iattr); if ( error ) { printk("obdfs_notify_change: obd_setattr fails (%d)\n", error); return error; } else { inode_setattr(inode, iattr); } EXIT; return error; } static int obdfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize) { struct statfs tmp; struct obdfs_sb_info * sbi; int error; ENTRY; sbi = sb->u.generic_sbp; error = obd_statfs(sbi->osi_conn_info.conn_id, &tmp); if ( error ) { printk("obdfs_notify_change: obd_statfs fails (%d)\n", error); return error; } copy_to_user(buf, &tmp, (bufsize