modulefs_DATA = smfs.o
EXTRA_PROGRAMS = smfs
-smfs_SOURCES = super.c options.c inode.c cache.c dir.c
-
+smfs_SOURCES = super.c options.c inode.c cache.c dir.c
+smfs_SOURCES += sysctl.c file.c symlink.c sm_fs.c
include $(top_srcdir)/Rules
extern struct address_space_operations smfs_file_aops;
extern struct inode_operations smfs_sym_iops;
extern struct file_operations smfs_sym_fops;
+extern struct super_operations smfs_super_ops;
inline struct super_operations *cache_sops(struct sm_ops *smfs_ops)
{
}
void cleanup_smfs_cache()
{
-
+ return;
}
static void setup_sm_symlink_ops(struct inode *cache_inode,
if (cache_inode->i_op->getxattr)
iops->getxattr = cache_iops->getxattr;
if (cache_inode->i_op->listxattr)
- iops->setxattr = cache_iops->setxattr;
+ iops->listxattr = cache_iops->listxattr;
if (cache_inode->i_op->removexattr)
iops->removexattr = cache_iops->removexattr;
}
}
return;
}
-void sm_setup_inode_ops(struct inode *cache_inode, struct inode *inode)
+
+static void setup_sm_sb_ops(struct super_block *cache_sb,
+ struct super_block *sb,
+ struct super_operations *smfs_sops)
+{
+ struct smfs_super_info *smb;
+ struct super_operations *sops;
+
+ ENTRY;
+
+ smb = S2SMI(sb);
+
+ if (smb->ops_check & SB_OPS_CHECK)
+ return;
+ smb->ops_check |= SB_OPS_CHECK;
+ sops = cache_sops(&smfs_operations);
+ memset(sops, 0, sizeof (struct super_operations));
+
+ if (cache_sb->s_op) {
+ if (cache_sb->s_op->read_inode)
+ sops->read_inode = smfs_sops->read_inode;
+ if (cache_sb->s_op->read_inode2)
+ sops->read_inode2 = smfs_sops->read_inode2;
+ if (cache_sb->s_op->dirty_inode)
+ sops->dirty_inode = smfs_sops->dirty_inode;
+ if (cache_sb->s_op->write_inode)
+ sops->write_inode = smfs_sops->write_inode;
+ if (cache_sb->s_op->put_inode)
+ sops->put_inode = smfs_sops->put_inode;
+ if (cache_sb->s_op->delete_inode)
+ sops->delete_inode = smfs_sops->delete_inode;
+ if (cache_sb->s_op->put_super)
+ sops->put_super = smfs_sops->put_super;
+ if (cache_sb->s_op->write_super)
+ sops->write_super = smfs_sops->write_super;
+ if (cache_sb->s_op->write_super_lockfs)
+ sops->write_super_lockfs = smfs_sops->write_super_lockfs;
+ if (cache_sb->s_op->unlockfs)
+ sops->unlockfs = smfs_sops->unlockfs;
+ if (cache_sb->s_op->statfs)
+ sops->statfs = smfs_sops->statfs;
+ if (cache_sb->s_op->remount_fs)
+ sops->remount_fs = smfs_sops->remount_fs;
+ if (cache_sb->s_op->clear_inode)
+ sops->clear_inode = smfs_sops->clear_inode;
+ if (cache_sb->s_op->umount_begin)
+ sops->umount_begin = smfs_sops->umount_begin;
+ if (cache_sb->s_op->fh_to_dentry)
+ sops->fh_to_dentry = smfs_sops->fh_to_dentry;
+ if (cache_sb->s_op->dentry_to_fh)
+ sops->dentry_to_fh = smfs_sops->dentry_to_fh;
+ if (cache_sb->s_op->show_options)
+ sops->show_options = smfs_sops->show_options;
+ }
+
+ return;
+}
+void sm_set_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) ) {
+ if (!cache_fiops(&smfs_operations)) {
setup_sm_file_ops(cache_inode, inode,
&smfs_file_iops,
&smfs_file_fops,
inode->i_ino, inode->i_op);
}
}
+void sm_set_sb_ops (struct super_block *cache_sb,
+ struct super_block *sb)
+{
+ struct smfs_super_info *smb;
+
+ smb = S2SMI(sb);
+
+ if (smb->ops_check & SB_OPS_CHECK)
+ return;
+ smb->ops_check |= SB_OPS_CHECK;
+ if (!cache_sops(&smfs_operations)) {
+ setup_sm_sb_ops(cache_sb, sb, &smfs_super_ops);
+ }
+ sb->s_op = cache_sops(&smfs_operations);
+ return;
+}
if (!inode)
GOTO(exit, rc);
- sm_setup_inode_ops(cache_inode, inode);
+ sm_set_inode_ops(cache_inode, inode);
exit:
d_unalloc(cache_dentry);
RETURN(rc);
--- /dev/null
+/*
+ * file.c
+ */
+
+#define DEBUG_SUBSYSTEM S_SM
+
+#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 <linux/pagemap.h>
+#include "smfs_internal.h"
+
+struct address_space_operations smfs_file_aops = {
+};
+
+struct file_operations smfs_file_fops = {
+};
+
+struct inode_operations smfs_file_iops = {
+};
+
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);
+ sm_set_inode_ops(cache_inode, inode);
CDEBUG(D_INODE, "read_inode ino %lu icount %d \n",
inode->i_ino, atomic_read(&inode->i_count));
clear_inode(cache_inode);
return;
}
-struct super_operations currentfs_super_ops = {
+
+struct super_operations smfs_super_ops = {
read_inode: smfs_read_inode,
clear_inode: smfs_clear_inode,
+ put_super: smfs_put_super,
};
--- /dev/null
+/*
+ * fs/smfs/sm_fs.c
+ *
+ * A storage management file system.
+ *
+ */
+#define EXPORT_SYMTAB
+#define DEBUG_SUBSYSTEM S_SM
+
+#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 <linux/miscdevice.h>
+
+#include "smfs_internal.h"
+
+int sm_stack = 0;
+long sm_kmemory = 0;
+
+
+MODULE_AUTHOR("Peter J. Braam <braam@cs.cmu.edu>");
+MODULE_DESCRIPTION("Smfs file system filters v0.01");
+
+extern int init_smfs(void);
+extern int cleanup_smfs(void);
+extern int init_snap_sysctl(void);
+
+static int __init smfs_init(void)
+{
+ int err;
+
+ if ( (err = init_smfs()) ) {
+ printk("Error initializing snapfs, %d\n", err);
+ return -EINVAL;
+ }
+
+ if ( (err = init_smfs_proc_sys()) ) {
+ printk("Error initializing snapfs proc sys, %d\n", err);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void __exit smfs_cleanup(void)
+{
+ cleanup_smfs();
+}
+module_init(smfs_init);
+module_exit(smfs_cleanup);
+
char *value;
struct list_head list;
};
+
+extern int init_smfs_proc_sys(void);
/*options.c*/
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_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);
-
+/*super.c*/
+int init_smfs(void);
+int cleanup_smfs(void);
+void smfs_put_super(struct super_block *sb);
/*sysctl.c*/
extern int sm_debug_level;
extern int sm_inodes;
*
* Author: Peter J. Braam <braam@mountainviewdata.com>
*/
-#define DEBUG_SUBSYSTEM S_SNAP
+#define DEBUG_SUBSYSTEM S_SM
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/fs.h>
-#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/utime.h>
+#include <linux/file.h>
+#include <linux/slab.h>
#include <linux/loop.h>
#include <linux/errno.h>
#include "smfs_internal.h"
write_unlock(&files->file_lock);
RETURN(-1);
}
+static int close_fd(int fd)
+{
+ struct files_struct *files = current->files;
+
+ write_lock(&files->file_lock);
+
+ files->fd[fd] = NULL;
+ __put_unused_fd(files, fd);
+
+ write_unlock(&files->file_lock);
+ return 0;
+}
+
#define MAX_LOOP_DEVICES 256
static char *parse_path2dev(struct super_block *sb, char *dev_path)
{
filp = filp_open(dev_path, 0, 0);
if (!filp)
RETURN(NULL);
-
if (S_ISREG(filp->f_dentry->d_inode->i_mode)) {
/*here we must walk through all the snap cache to
*find the loop device */
+
+ fd = get_unused_fd();
+ if (!fd) RETURN(NULL);
+
+ fd_install(fd, filp);
+ SM_ALLOC(name, strlen("/dev/loop/") + 2);
+
for (i = 0; i < MAX_LOOP_DEVICES; i++) {
fd = get_fd(filp);
- error = sb->s_bdev->bd_op->ioctl(filp->f_dentry->d_inode,
- filp, LOOP_SET_FD,
- (unsigned long)&fd);
- if (!error) {
- filp_close(filp, current->files);
- /*FIXME later, the loop file should
+ if (fd > 0) {
+ struct block_device_operations *bd_ops;
+ struct dentry *dentry;
+ struct nameidata nd;
+ /*FIXME later, the loop file should
*be different for different system*/
- SM_ALLOC(name, strlen("/dev/loop/") + 2);
- sprintf(name, "dev/loop/%d", i);
- RETURN(name);
+
+ sprintf(name, "/dev/loop/%d", i);
+
+ if (path_init(name, LOOKUP_FOLLOW, &nd)) {
+ error = path_walk(name, &nd);
+ if (error) {
+ path_release(&nd);
+ SM_FREE(name, sizeof(name) + 1);
+ RETURN(NULL);
+ }
+ } else {
+ SM_FREE(name, sizeof(name) + 1);
+ RETURN(NULL);
+ }
+ dentry = nd.dentry;
+ bd_ops = get_blkfops(LOOP_MAJOR);
+ error = bd_ops->ioctl(dentry->d_inode,
+ filp, LOOP_SET_FD,
+ (unsigned long)fd);
+ path_release(&nd);
+ if (!error) {
+ filp_close(filp, current->files);
+ RETURN(name);
+ }
}
}
}
return err;
}
+static int sm_umount_cache(struct super_block *sb)
+{
+ struct smfs_super_info *smb = S2SMI(sb);
+
+ mntput(smb->smsi_mnt);
+ return 0;
+}
+void smfs_put_super(struct super_block *sb)
+{
+ if (sb)
+ sm_umount_cache(sb);
+ return;
+}
struct super_block *
smfs_read_super(
--- /dev/null
+/*
+ * fs/snap/snap.c
+ *
+ * A snap shot file system.
+ *
+ */
+#define DEBUG_SUBSYSTEM S_SNAP
+
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "smfs_internal.h"
+
+struct inode_operations smfs_sym_iops = {
+};
+
+struct file_operations smfs_sym_fops = {
+};
--- /dev/null
+/*
+ * Sysctrl entries for Snapfs
+ */
+
+/* /proc entries */
+
+#define DEBUG_SUBSYSTEM S_SNAP
+
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+
+#include "smfs_internal.h"
+
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_smfs_root;
+#endif
+
+
+/* SYSCTL below */
+
+static struct ctl_table_header *smfs_table_header = NULL;
+/* 0x100 to avoid any chance of collisions at any point in the tree with
+ * non-directories
+ */
+#define PSDEV_SMFS (0x130)
+
+#define PSDEV_DEBUG 1 /* control debugging */
+#define PSDEV_TRACE 2 /* control enter/leave pattern */
+
+/* These are global control options */
+#define ENTRY_CNT 3
+
+int sm_print_entry = 1;
+int sm_debug_level = 0;
+
+/* XXX - doesn't seem to be working in 2.2.15 */
+static struct ctl_table smfs_ctltable[] =
+{
+ {PSDEV_DEBUG, "debug", &sm_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
+ {PSDEV_TRACE, "trace", &sm_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
+ {0}
+};
+
+static ctl_table smfs_table[2] = {
+ {PSDEV_SMFS, "smfs", NULL, 0, 0555, smfs_ctltable},
+ {0}
+};
+
+
+int __init init_smfs_proc_sys(void)
+{
+#ifdef CONFIG_PROC_FS
+ proc_smfs_root = proc_mkdir("smfs", proc_root_fs);
+ if (!proc_smfs_root) {
+ printk(KERN_ERR "SMFS: error registering /proc/fs/smfs\n");
+ RETURN(-ENOMEM);
+ }
+ proc_smfs_root->owner = THIS_MODULE;
+#endif
+
+#ifdef CONFIG_SYSCTL
+ if ( !smfs_table_header )
+ smfs_table_header =
+ register_sysctl_table(smfs_table, 0);
+#endif
+ return 0;
+}
+
+void cleanup_smfs_proc_sys(void)
+{
+#ifdef CONFIG_SYSCTL
+ if ( smfs_table_header )
+ unregister_sysctl_table(smfs_table_header);
+ smfs_table_header = NULL;
+#endif
+#if CONFIG_PROC_FS
+ remove_proc_entry("smfs", proc_root_fs);
+#endif
+}
+