4 * Copyright (C) 1998 Peter J. Braam
5 * Copyright (C) 2000 Stelias Computing, Inc.
6 * Copyright (C) 2000 Red Hat, Inc.
7 * Copyright (C) 2000 Mountain View Data, Inc.
9 * Author: Peter J. Braam <braam@mountainviewdata.com>
11 #define DEBUG_SUBSYSTEM S_SNAP
13 #include <linux/module.h>
14 #include <linux/kmod.h>
15 #include <linux/init.h>
17 #include <linux/slab.h>
18 #include <linux/string.h>
19 #include <linux/loop.h>
20 #include <linux/errno.h>
21 #include "smfs_internal.h"
23 /* Find the options for the clone. These consist of a cache device
24 and an index in the snaptable associated with that device.
26 static char *smfs_options(char *options, char **devstr, char **namestr)
28 struct option *opt_value = NULL;
31 while (!(get_opt(&opt_value, &pos))) {
32 if (!strcmp(opt_value->opt, "dev")) {
34 *devstr = opt_value->value;
35 } else if (!strcmp(opt_value->opt, "type")) {
37 *namestr = opt_value->value;
44 static int get_fd(struct file *filp)
46 struct files_struct *files = current->files;
49 write_lock(&files->file_lock);
50 for (fd = 0; fd < files->max_fds; fd++) {
51 if(files->fd[fd] == filp) {
52 write_unlock(&files->file_lock);
56 write_unlock(&files->file_lock);
59 #define MAX_LOOP_DEVICES 256
60 static char *parse_path2dev(struct super_block *sb, char *dev_path)
63 int i = 0, fd = 0, error = 0;
66 filp = filp_open(dev_path, 0, 0);
70 if (S_ISREG(filp->f_dentry->d_inode->i_mode)) {
71 /*here we must walk through all the snap cache to
72 *find the loop device */
73 for (i = 0; i < MAX_LOOP_DEVICES; i++) {
75 error = sb->s_bdev->bd_op->ioctl(filp->f_dentry->d_inode,
79 filp_close(filp, current->files);
80 /*FIXME later, the loop file should
81 *be different for different system*/
82 SM_ALLOC(name, strlen("/dev/loop/") + 2);
83 sprintf(name, "dev/loop/%d", i);
88 SM_ALLOC(name, strlen(dev_path) + 1);
89 memcpy(name, dev_path, strlen(dev_path) + 1);
90 filp_close(filp, current->files);
93 extern struct super_operations smfs_super_ops;
95 static int sm_mount_cache(struct super_block *sb,
100 struct smfs_super_info *smb;
101 char *dev_name = NULL;
105 dev_name = parse_path2dev(sb, devstr);
107 GOTO(err_out, err = -ENOMEM);
109 if (!(page = __get_free_page(GFP_KERNEL))) {
110 GOTO(err_out, err = -ENOMEM);
112 memset((void *)page, 0, PAGE_SIZE);
113 sprintf((char *)page, "iopen_nopriv");
115 mnt = do_kern_mount(typestr, 0, dev_name, (void *)page);
119 CERROR("do_kern_mount failed: rc = %d\n", err);
123 smb->smsi_sb = mnt->mnt_sb;
127 SM_FREE(dev_name, strlen(dev_name) + 2);
134 struct super_block *sb,
138 struct smfs_inode_info *smi;
139 struct dentry *bottom_root;
140 struct inode *root_inode = NULL;
141 char *devstr = NULL, *typestr = NULL;
148 CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
151 /* read and validate options */
152 cache_data = smfs_options(data, &devstr, &typestr);
154 CERROR("invalid mount option %s\n", (char*)data);
155 GOTO(out_err, err=-EINVAL);
157 if (!typestr || !devstr) {
158 CERROR("mount options name and dev mandatory\n");
159 GOTO(out_err, err=-EINVAL);
162 err = sm_mount_cache(sb, devstr, typestr);
164 CERROR("Can not mount %s as %s\n", devstr, typestr);
167 /* set up the super block */
168 sb->s_op = &smfs_super_ops;
170 bottom_root = dget(S2SMI(sb)->smsi_sb->s_root);
172 CERROR("bottom not mounted\n");
173 GOTO(out_err, err=-ENOENT);
176 root_ino = bottom_root->d_inode->i_ino;
177 smi = I2SMI(root_inode);
178 /*FIXME Intialize smi here*/
180 CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
181 sb->s_op->read_inode, root_ino, root_inode);
183 sb->s_root = d_alloc_root(bottom_root->d_inode);
186 GOTO(out_err, err=-EINVAL);
189 CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
190 (ulong) sb, (ulong) &sb->u.generic_sbp);
199 static DECLARE_FSTYPE(smfs_type, "smfs", smfs_read_super, 0);
205 err = register_filesystem(&smfs_type);
207 CERROR("smfs: failed in register Storage Management filesystem!\n");
212 int cleanup_smfs(void)
217 err = unregister_filesystem(&smfs_type);
219 CERROR("smfs: failed to unregister Storage Management filesystem!\n");