--- /dev/null
+/*
+ * snapfs/cache.c
+ */
+
+#define DEBUG_SUBSYSTEM S_SM
+
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <portals/list.h>
+#include "smfs_internal.h"
+struct sm_ops smfs_operations;
+
+extern struct inode_operations smfs_file_iops;
+extern struct file_operations smfs_file_fops;
+extern struct address_space_operations smfs_file_aops;
+extern struct inode_operations smfs_sym_iops;
+extern struct file_operations smfs_sym_fops;
+
+inline struct super_operations *cache_sops(struct sm_ops *smfs_ops)
+{
+ return &smfs_ops->sm_sb_ops;
+}
+
+inline struct inode_operations *cache_diops(struct sm_ops *smfs_ops)
+{
+ return &smfs_ops->sm_dir_iops;
+}
+
+inline struct inode_operations *cache_fiops(struct sm_ops *smfs_ops)
+{
+ return &smfs_ops->sm_file_iops;
+}
+
+inline struct inode_operations *cache_siops(struct sm_ops *smfs_ops)
+{
+ return &smfs_ops->sm_sym_iops;
+}
+
+inline struct file_operations *cache_dfops(struct sm_ops *smfs_ops)
+{
+ return &smfs_ops->sm_dir_fops;
+}
+
+inline struct file_operations *cache_ffops(struct sm_ops *smfs_ops)
+{
+ return &smfs_ops->sm_file_fops;
+}
+
+inline struct address_space_operations *cache_faops(struct sm_ops *smfs_ops)
+{
+ return &smfs_ops->sm_file_aops;
+}
+
+inline struct file_operations *cache_sfops(struct sm_ops *smfs_ops)
+{
+ return &smfs_ops->sm_sym_fops;
+}
+
+inline struct dentry_operations *cache_dops(struct sm_ops *smfs_ops)
+{
+ return &smfs_ops->sm_dentry_ops;
+}
+
+void init_smfs_cache()
+{
+ memset(&smfs_operations, 0, sizeof(struct sm_ops));
+}
+void cleanup_smfs_cache()
+{
+
+}
+
+static void setup_sm_symlink_ops(struct inode *cache_inode,
+ struct inode *inode,
+ struct inode_operations *cache_sym_iops,
+ struct file_operations *cache_sym_fops)
+{
+ return;
+}
+
+static void setup_sm_file_ops(struct inode *cache_inode,
+ struct inode *inode,
+ struct inode_operations *cache_iops,
+ struct file_operations *cache_fops,
+ struct address_space_operations *cache_aops)
+{
+
+ struct smfs_super_info *smb;
+ struct inode_operations *iops;
+ struct file_operations *fops;
+ struct address_space_operations *aops;
+
+ smb = S2SMI(inode->i_sb);
+
+ if (smb->ops_check & FILE_OPS_CHECK)
+ return;
+ smb->ops_check |= FILE_OPS_CHECK;
+
+ iops = cache_fiops(&smfs_operations);
+ fops = cache_ffops(&smfs_operations);
+ aops = cache_faops(&smfs_operations);
+
+ memset(iops , 0 , sizeof (struct inode_operations));
+ memset(fops , 0 , sizeof (struct file_operations));
+ memset(aops , 0 , sizeof (struct address_space_operations));
+
+ if (cache_inode->i_op) {
+ if (cache_inode->i_op->create)
+ iops->create = cache_iops->create;
+ if (cache_inode->i_op->create_it)
+ iops->create_it = cache_iops->create_it;
+ if (cache_inode->i_op->lookup)
+ iops->lookup = cache_iops->lookup;
+ if (cache_inode->i_op->lookup_raw)
+ iops->lookup_raw = cache_iops->lookup_raw;
+ if (cache_inode->i_op->lookup_it)
+ iops->lookup_it = cache_iops->lookup_it;
+ if (cache_inode->i_op->link)
+ iops->link = cache_iops->link;
+ if (cache_inode->i_op->link_raw)
+ iops->link_raw = cache_iops->link_raw;
+ if (cache_inode->i_op->unlink)
+ iops->unlink = cache_iops->unlink;
+ if (cache_inode->i_op->unlink_raw)
+ iops->unlink_raw = cache_iops->unlink_raw;
+ if (cache_inode->i_op->symlink)
+ iops->symlink = cache_iops->symlink;
+ if (cache_inode->i_op->symlink_raw)
+ iops->symlink_raw = cache_iops->symlink_raw;
+ if (cache_inode->i_op->mkdir)
+ iops->mkdir = cache_iops->mkdir;
+ if (cache_inode->i_op->mkdir_raw)
+ iops->mkdir_raw = cache_iops->mkdir_raw;
+ if (cache_inode->i_op->rmdir)
+ iops->rmdir = cache_iops->rmdir;
+ if (cache_inode->i_op->rmdir_raw)
+ iops->rmdir_raw = cache_iops->rmdir_raw;
+ if (cache_inode->i_op->mknod)
+ iops->mknod = cache_iops->mknod;
+ if (cache_inode->i_op->mknod_raw)
+ iops->mknod_raw = cache_iops->mknod_raw;
+ if (cache_inode->i_op->rename)
+ iops->rename = cache_iops->rename;
+ if (cache_inode->i_op->rename_raw)
+ iops->rename_raw = cache_iops->rename_raw;
+ if (cache_inode->i_op->readlink)
+ iops->readlink = cache_iops->readlink;
+ if (cache_inode->i_op->follow_link)
+ iops->follow_link = cache_iops->follow_link;
+ if (cache_inode->i_op->truncate)
+ iops->truncate = cache_iops->truncate;
+ if (cache_inode->i_op->permission)
+ iops->permission = cache_iops->permission;
+ if (cache_inode->i_op->revalidate)
+ iops->revalidate = cache_iops->revalidate;
+ if (cache_inode->i_op->revalidate_it)
+ iops->revalidate_it = cache_iops->revalidate_it;
+ if (cache_inode->i_op->setattr)
+ iops->setattr = cache_iops->setattr;
+ if (cache_inode->i_op->setattr_raw)
+ iops->setattr_raw = cache_iops->setattr_raw;
+ if (cache_inode->i_op->getattr)
+ iops->getattr = cache_iops->getattr;
+ if (cache_inode->i_op->setxattr)
+ iops->setxattr = cache_iops->setxattr;
+ if (cache_inode->i_op->getxattr)
+ iops->getxattr = cache_iops->getxattr;
+ if (cache_inode->i_op->listxattr)
+ iops->setxattr = cache_iops->setxattr;
+ if (cache_inode->i_op->removexattr)
+ iops->removexattr = cache_iops->removexattr;
+ }
+ if (cache_inode->i_fop) {
+
+ }
+ if (cache_inode->i_mapping && cache_inode->i_mapping->a_ops) {
+
+ }
+ return;
+}
+void sm_setup_inode_ops(struct inode *cache_inode, struct inode *inode)
+{
+ /* XXX now set the correct snap_{file,dir,sym}_iops */
+ if (S_ISDIR(inode->i_mode)) {
+ inode->i_op = cache_diops(&smfs_operations);
+ inode->i_fop = cache_dfops(&smfs_operations);
+ } else if (S_ISREG(inode->i_mode)) {
+ if (!cache_fiops(&smfs_operations) ) {
+ setup_sm_file_ops(cache_inode, inode,
+ &smfs_file_iops,
+ &smfs_file_fops,
+ &smfs_file_aops);
+ }
+ CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
+ inode->i_ino, inode->i_op);
+ inode->i_fop = cache_ffops(&smfs_operations);
+ inode->i_op = cache_fiops(&smfs_operations);
+ if (inode->i_mapping)
+ inode->i_mapping->a_ops = cache_faops(&smfs_operations);
+
+ }
+ else if (S_ISLNK(inode->i_mode)) {
+ if (!cache_siops(&smfs_operations)) {
+ setup_sm_symlink_ops(cache_inode, inode,
+ &smfs_sym_iops, &smfs_sym_fops);
+ }
+ inode->i_op = cache_siops(&smfs_operations);
+ inode->i_fop = cache_sfops(&smfs_operations);
+ CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
+ inode->i_ino, inode->i_op);
+ }
+}
+
--- /dev/null
+/*
+ * dir.c
+ */
+#define DEBUG_SUBSYSTEM S_SNAP
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+
+#include "smfs_internal.h"
+
+static void d_unalloc(struct dentry *dentry)
+{
+ if (dentry) {
+ list_del(&dentry->d_hash);
+ INIT_LIST_HEAD(&dentry->d_hash);
+ dput(dentry);
+ }
+}
+static struct inode *sm_create_inode(struct super_block *sb,
+ struct inode *cache_inode)
+{
+ struct inode *inode;
+
+ inode = new_inode(sb);
+ if (inode) {
+ /*FIXME there are still some
+ * other attributes need to
+ * duplicated*/
+ inode->i_ino = cache_inode->i_ino;
+ inode->i_mode = cache_inode->i_mode;
+ }
+
+ return inode;
+}
+
+static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
+{
+ atomic_set(&dentry->d_count, 1);
+ dentry->d_vfs_flags = 0;
+ dentry->d_flags = 0;
+ dentry->d_inode = inode;
+ dentry->d_op = NULL;
+ dentry->d_fsdata = NULL;
+ dentry->d_mounted = 0;
+ INIT_LIST_HEAD(&dentry->d_hash);
+ INIT_LIST_HEAD(&dentry->d_lru);
+ INIT_LIST_HEAD(&dentry->d_subdirs);
+ INIT_LIST_HEAD(&dentry->d_alias);
+}
+
+static int smfs_create(struct inode *dir,
+ struct dentry *dentry,
+ int mode)
+{
+ struct inode *cache_dir;
+ struct inode *cache_inode, *inode;
+ struct dentry tmp;
+ struct dentry *cache_dentry;
+ int rc;
+
+ ENTRY;
+
+ cache_dir = I2CI(dir);
+ if (!cache_dir)
+ RETURN(-ENOENT);
+
+ prepare_parent_dentry(&tmp, cache_dir);
+ cache_dentry = d_alloc(&tmp, &dentry->d_name);
+
+ if (!cache_dentry)
+ RETURN(-ENOENT);
+
+ if(cache_dir && cache_dir->i_op->create)
+ rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode);
+ if (rc)
+ GOTO(exit, rc);
+
+ cache_inode = cache_dentry->d_inode;
+ inode = sm_create_inode(dir->i_sb, cache_inode);
+
+ if (!inode)
+ GOTO(exit, rc);
+
+ sm_setup_inode_ops(cache_inode, inode);
+exit:
+ d_unalloc(cache_dentry);
+ RETURN(rc);
+}
+
+struct inode_operations smfs_dir_fops = {
+ create: smfs_create,
+};
+
--- /dev/null
+/*
+ * fs/snap/snap.c
+ *
+ * A snap shot file system.
+ *
+ */
+
+#define DEBUG_SUBSYSTEM S_SM
+
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include "smfs_internal.h"
+
+
+static void smfs_read_inode(struct inode *inode)
+{
+ struct super_block *cache_sb;
+ struct inode *cache_inode;
+ ENTRY;
+
+ if (!inode)
+ return;
+
+ CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
+ cache_sb = S2CSB(inode->i_sb);
+
+ cache_inode = new_inode(cache_sb);
+ I2CI(inode) = cache_inode;
+
+ if(cache_sb && cache_sb->s_op->read_inode)
+ cache_sb->s_op->read_inode(cache_inode);
+
+ CDEBUG(D_INODE, "read_inode ino %lu icount %d \n",
+ inode->i_ino, atomic_read(&inode->i_count));
+
+ sm_setup_inode_ops(cache_inode, inode);
+
+ CDEBUG(D_INODE, "read_inode ino %lu icount %d \n",
+ inode->i_ino, atomic_read(&inode->i_count));
+
+ return;
+}
+/* Although some filesystem(such as ext3) do not have
+ * clear_inode method, but we need it to free the
+ * cache inode
+ */
+static void smfs_clear_inode(struct inode *inode)
+{
+ struct super_block *cache_sb;
+ struct inode *cache_inode;
+
+ ENTRY;
+
+ if (!inode) return;
+
+ cache_sb = S2CSB(inode->i_sb);
+ cache_inode = I2CI(inode);
+ clear_inode(cache_inode);
+ return;
+}
+struct super_operations currentfs_super_ops = {
+ read_inode: smfs_read_inode,
+ clear_inode: smfs_clear_inode,
+};
+
+
+
+
+
struct smfs_super_info {
struct super_block *smsi_sb;
- struct vfsmnt *smsi_mnt; /* mount the cache kere with kern_do_mount (like MDS) */
+ struct vfsmount *smsi_mnt; /* mount the cache kere with kern_do_mount (like MDS) */
+ int ops_check;
};
#define I2SMI(inode) ((struct smfs_inode_info *) (&(inode->u.generic_ip)))
#define S2SMI(sb) ((struct smfs_super_info *) (&(sb->u.generic_sbp)))
+#define S2CSB(sb) (((struct smfs_super_info *) (&(sb->u.generic_sbp)))->smsi_sb)
+#define I2CI(inode) (((struct smfs_inode_info*) (&(inode->u.generic_ip)))->smi_inode)
+
+#define SB_OPS_CHECK 0x1
+#define INODE_OPS_CHECK 0x2
+#define FILE_OPS_CHECK 0x4
+#define DENTRY_OPS_CHECK 0x8
+#define DEV_OPS_CHECK 0x10
+#define SYMLINK_OPS_CHECK 0x20
+#define DIR_OPS_CHECK 0x40
#include "smfs_support.h"
+struct sm_ops {
+ /* operations on the file store */
+ struct super_operations sm_sb_ops;
+
+ struct inode_operations sm_dir_iops;
+ struct inode_operations sm_file_iops;
+ struct inode_operations sm_sym_iops;
+
+ struct file_operations sm_dir_fops;
+ struct file_operations sm_file_fops;
+ struct file_operations sm_sym_fops;
+
+ struct address_space_operations sm_file_aops;
+ struct dentry_operations sm_dentry_ops;
+};
+
struct option {
char *opt;
char *value;
extern int get_opt(struct option **option, char **pos);
extern void cleanup_option(void);
extern int init_option(char *data);
+/*cache.c*/
+void sm_setup_inode_ops(struct inode *cache_inode, struct inode *inode);
+void sm_set_sb_ops(struct super_block *cache_sb, struct super_block *sb);
+void init_smfs_cache(void);
+void cleanup_smfs_cache(void);
+
/*sysctl.c*/
extern int sm_debug_level;
extern int sm_inodes;