#include <linux/lustre_smfs.h>
#include "smfs_internal.h"
-static char *smfs_options(char *data, char **devstr, char **namestr,
- int *kml, int *cache, char **opts, int *iopen_nopriv,
- int *cow)
-{
- char *pos;
- struct option *opt_value = NULL;
-
- while (!(get_opt(&opt_value, &pos))) {
- if (!strcmp(opt_value->opt, "dev")) {
- if (devstr != NULL)
- *devstr = opt_value->value;
- } else if (!strcmp(opt_value->opt, "type")) {
- if (namestr != NULL)
- *namestr = opt_value->value;
- } else if (!strcmp(opt_value->opt, "kml")) {
- if (kml)
- *kml = 1;
- } else if (!strcmp(opt_value->opt, "cache")) {
- if (cache)
- *cache = 1;
- } else if (!strcmp(opt_value->opt, "options")) {
- if (opts != NULL)
- *opts = opt_value->value;
- } else if (!strcmp(opt_value->opt, "iopen_nopriv")) {
- if (iopen_nopriv != NULL)
- *iopen_nopriv = 1;
- } else if (!strcmp(opt_value->opt, "snap")) {
- *cow = 1;
- } else {
- break;
- }
- }
- return pos;
-}
-
-struct vfsmount *get_vfsmount(struct super_block *sb)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static struct super_block *smfs_read_super(struct super_block *sb,
+ void *data, int silent)
{
- struct vfsmount *rootmnt, *mnt, *ret = NULL;
- struct list_head *end, *list;
+ int err;
- rootmnt = mntget(current->fs->rootmnt);
- end = list = &rootmnt->mnt_list;
- do {
- mnt = list_entry(list, struct vfsmount, mnt_list);
- if (mnt->mnt_sb == sb) {
- ret = mnt;
- break;
- }
- list = list->next;
- } while (end != list);
+ err = smfs_fill_super(sb, data, silent);
+ if (err)
+ return NULL;
- mntput(current->fs->rootmnt);
- return ret;
+ return sb;
}
-struct super_block *smfs_get_sb_by_path(char *path, int len)
-{
- struct super_block *sb;
- struct nameidata nd;
- int error = 0;
-
- ENTRY;
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- if (path_init(path, LOOKUP_FOLLOW, &nd)) {
+static struct file_system_type smfs_type = {
+ .owner = THIS_MODULE,
+ .name = "smfs",
+ .read_super = smfs_read_super,
+};
#else
- if (path_lookup(path, LOOKUP_FOLLOW, &nd)) {
-#endif
- error = path_walk(path, &nd);
- if (error) {
- path_release(&nd);
- RETURN(NULL);
- }
- } else {
- RETURN(NULL);
- }
-
- /* FIXME-WANGDI: add some check code here. */
- sb = nd.dentry->d_sb;
- path_release(&nd);
- RETURN(sb);
-}
-
-static int smfs_init_fsfilt_ops(struct super_block *sb)
+struct super_block *smfs_get_super(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+ void *data)
{
- ENTRY;
- if (!S2SMI(sb)->sm_cache_fsfilt) {
- S2SMI(sb)->sm_cache_fsfilt =
- fsfilt_get_ops(S2SMI(sb)->smsi_cache_ftype);
- if (!S2SMI(sb)->sm_cache_fsfilt) {
- CERROR("Can not get %s fsfilt ops needed by kml\n",
- S2SMI(sb)->smsi_cache_ftype);
- RETURN(-EINVAL);
- }
- }
- if (!S2SMI(sb)->sm_fsfilt) {
- S2SMI(sb)->sm_fsfilt =
- fsfilt_get_ops(S2SMI(sb)->smsi_ftype);
- if (!S2SMI(sb)->sm_fsfilt) {
- CERROR("Can not get %s fsfilt ops needed by kml\n",
- S2SMI(sb)->smsi_ftype);
- RETURN(-EINVAL);
- }
- }
- RETURN(0);
+ return get_sb_nodev(fs_type, flags, data, smfs_fill_super);
}
-void smfs_cleanup_fsfilt_ops(struct super_block *sb)
+void smfs_kill_super(struct super_block *sb)
{
- if (S2SMI(sb)->sm_cache_fsfilt)
- fsfilt_put_ops(S2SMI(sb)->sm_cache_fsfilt);
- if (S2SMI(sb)->sm_fsfilt)
- fsfilt_put_ops(S2SMI(sb)->sm_fsfilt);
+ kill_anon_super(sb);
}
-static int sm_mount_cache(struct super_block *sb, char *devstr,
- char *typestr, char *opts, int iopen_nopriv)
-{
- struct smfs_super_info *smb;
- int err = 0, typelen;
- struct vfsmount *mnt;
- unsigned long page;
- ENTRY;
-
- typelen = strlen(typestr);
-
- page = __get_free_page(GFP_KERNEL);
- if (!page)
- GOTO(err_out, err = -ENOMEM);
-
- memset((void *)page, 0, PAGE_SIZE);
-
- if (iopen_nopriv)
- sprintf((char *)page, "iopen_nopriv");
-
- if (opts && strlen(opts)) {
- int n = strlen((char *)page);
- sprintf((char *)page + n, ",%s", opts);
- }
-
- printk("smfs: mounting %s at %s\n", typestr, devstr);
-
- mnt = do_kern_mount(typestr, 0, devstr, (void *)page);
- free_page(page);
-
- if (IS_ERR(mnt)) {
- CERROR("do_kern_mount failed: rc = %ld\n", PTR_ERR(mnt));
- GOTO(err_out, err = PTR_ERR(mnt));
- }
- smb = S2SMI(sb);
- smb->smsi_sb = mnt->mnt_sb;
- smb->smsi_mnt = mnt;
-
- smfs_init_sm_ops(smb);
-
- OBD_ALLOC(smb->smsi_cache_ftype, strlen(typestr) + 1);
- memcpy(smb->smsi_cache_ftype, typestr, strlen(typestr));
-
- OBD_ALLOC(smb->smsi_ftype, strlen(SMFS_TYPE) + 1);
- memcpy(smb->smsi_ftype, SMFS_TYPE, strlen(SMFS_TYPE));
-
- duplicate_sb(sb, mnt->mnt_sb);
- sm_set_sb_ops(mnt->mnt_sb, sb);
- err = smfs_init_fsfilt_ops(sb);
-err_out:
- return err;
-}
+static struct file_system_type smfs_type = {
+ .owner = THIS_MODULE,
+ .name = "smfs",
+ .get_sb = smfs_get_super,
+ .kill_sb = smfs_kill_super,
+};
+#endif
-static int sm_umount_cache(struct super_block *sb)
+static int cleanup_smfs(void)
{
- struct smfs_super_info *smb = S2SMI(sb);
-
- iput(S2CSB(sb)->s_root->d_inode);
- dput(S2CSB(sb)->s_root);
- mntput(smb->smsi_mnt);
- smfs_cleanup_sm_ops(smb);
- smfs_cleanup_fsfilt_ops(sb);
-
- if (smb->smsi_cache_ftype)
- OBD_FREE(smb->smsi_cache_ftype,
- strlen(smb->smsi_cache_ftype) + 1);
-
- if (smb->smsi_ftype)
- OBD_FREE(smb->smsi_ftype, strlen(smb->smsi_ftype) + 1);
+ int err = 0;
+ err = unregister_filesystem(&smfs_type);
+ if (err)
+ CERROR("unregister_filesystem() failed, rc = %d\n", err);
return 0;
}
-void smfs_put_super(struct super_block *sb)
+static int init_smfs(void)
{
- if (SMFS_CACHE_HOOK(S2SMI(sb)))
- cache_space_hook_exit(sb);
- if (SMFS_DO_REC(S2SMI(sb)))
- smfs_rec_cleanup(sb);
- if (sb)
- sm_umount_cache(sb);
- return;
+ int err;
+
+ err = register_filesystem(&smfs_type);
+ if (err)
+ CERROR("register_filesystem() failed, rc = %d\n", err);
+ return err;
}
-static int smfs_fill_super(struct super_block *sb,
- void *data, int silent)
+static int __init smfs_init(void)
{
- ino_t root_ino;
- char *cache_data;
-
- int iopen_nopriv = 0;
- struct inode *root_inode = NULL;
- int err = 0, do_rec = 0, cache_hook = 0, do_cow = 0;
- char *devstr = NULL, *typestr = NULL, *opts = NULL;
-
- ENTRY;
-
- CDEBUG(D_SUPER, "mount opts: %s\n", data ?
- (char *)data : "(none)");
-
- init_option(data);
-
- /* read and validate passed options. */
- cache_data = smfs_options(data, &devstr, &typestr,
- &do_rec, &cache_hook, &opts,
- &iopen_nopriv, &do_cow);
-
- if (*cache_data)
- CWARN("smfs_fill_super(): options parsing stoped at "
- "option %s\n", cache_data);
+ int err;
- if (!typestr || !devstr) {
- CERROR("mount options name and dev mandatory\n");
- GOTO(out_err, err = -EINVAL);
+ if ( (err = init_smfs_psdev()) ) {
+ printk("Error initializing smfs_psdev, %d\n", err);
+ return -EINVAL;
}
- err = sm_mount_cache(sb, devstr, typestr, opts, iopen_nopriv);
- if (err) {
- CERROR("Can not mount %s as %s\n", devstr, typestr);
- GOTO(out_err, 0);
- }
-
- if (do_rec) smfs_rec_init(sb);
- if (cache_hook) cache_space_hook_init(sb);
-
- dget(S2CSB(sb)->s_root);
- root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
- root_inode = iget(sb, root_ino);
-
- CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
- sb->s_op->read_inode, root_ino, root_inode);
- sb->s_root = d_alloc_root(root_inode);
-
- if (!sb->s_root) {
- sm_umount_cache(sb);
- GOTO(out_err, err=-EINVAL);
+ if ( (err = init_smfs()) ) {
+ printk("Error initializing smfs, %d\n", err);
+ return -EINVAL;
}
-#if CONFIG_SNAP
- if (do_cow) smfs_cow_init(sb);
-#endif
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
- (ulong)sb, (ulong)&sb->u.generic_sbp);
-#else
- CDEBUG(D_SUPER, "sb %lx, &sb->s_fs_info: %lx\n",
- (ulong)sb, (ulong)&sb->s_fs_info);
-#endif
-
-out_err:
- cleanup_option();
- return err;
-}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static struct super_block *smfs_read_super(struct super_block *sb,
- void *data, int silent)
-{
- int err;
-
- err = smfs_fill_super(sb, data, silent);
- if (err)
- return NULL;
+ if ( (err = init_smfs_proc_sys()) ) {
+ printk("Error initializing smfs proc sys, %d\n", err);
+ return -EINVAL;
+ }
- return sb;
-}
-#else
-struct super_block *smfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
-{
- return get_sb_nodev(fs_type, flags, data, smfs_fill_super);
+ return 0;
}
-#endif
-
-static struct file_system_type smfs_type = {
- .owner = THIS_MODULE,
- .name = "smfs",
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- .read_super = smfs_read_super,
-#else
- .get_sb = smfs_get_sb,
- .kill_sb = kill_anon_super,
-#endif
-};
-int init_smfs(void)
+static void __exit smfs_cleanup(void)
{
- int err;
-
- err = register_filesystem(&smfs_type);
- if (err)
- CERROR("register_filesystem() failed, rc = %d\n", err);
- return err;
+ cleanup_smfs();
+ smfs_cleanup_psdev();
}
-int cleanup_smfs(void)
-{
- int err = 0;
+MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
+MODULE_DESCRIPTION("Smfs file system filters v0.01");
+MODULE_LICENSE("GPL");
- err = unregister_filesystem(&smfs_type);
- if (err)
- CERROR("unregister_filesystem() failed, rc = %d\n", err);
- return 0;
-}
+module_init(smfs_init);
+module_exit(smfs_cleanup);