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_SM
13 #include <linux/config.h>
14 #include <linux/module.h>
15 #include <linux/kmod.h>
16 #include <linux/init.h>
18 #include <linux/string.h>
20 #include <linux/utime.h>
21 #include <linux/file.h>
22 #include <linux/slab.h>
23 #include <linux/loop.h>
24 #include <linux/errno.h>
25 #include "smfs_internal.h"
27 /* Find the options for the clone. These consist of a cache device
28 and an index in the snaptable associated with that device.
30 static char *smfs_options(char *options, char **devstr, char **namestr)
32 struct option *opt_value = NULL;
35 while (!(get_opt(&opt_value, &pos))) {
36 if (!strcmp(opt_value->opt, "dev")) {
38 *devstr = opt_value->value;
39 } else if (!strcmp(opt_value->opt, "type")) {
41 *namestr = opt_value->value;
48 static int get_fd(struct file *filp)
50 struct files_struct *files = current->files;
53 write_lock(&files->file_lock);
54 for (fd = 0; fd < files->max_fds; fd++) {
55 if(files->fd[fd] == filp) {
56 write_unlock(&files->file_lock);
60 write_unlock(&files->file_lock);
63 static int close_fd(int fd)
65 struct files_struct *files = current->files;
67 write_lock(&files->file_lock);
70 __put_unused_fd(files, fd);
72 write_unlock(&files->file_lock);
76 #define MAX_LOOP_DEVICES 256
77 static char *parse_path2dev(struct super_block *sb, char *dev_path)
80 int i = 0, fd = 0, error = 0;
83 filp = filp_open(dev_path, 0, 0);
86 if (S_ISREG(filp->f_dentry->d_inode->i_mode)) {
87 /*here we must walk through all the snap cache to
88 *find the loop device */
91 if (!fd) RETURN(NULL);
94 SM_ALLOC(name, strlen("/dev/loop/") + 2);
96 for (i = 0; i < MAX_LOOP_DEVICES; i++) {
99 struct block_device_operations *bd_ops;
100 struct dentry *dentry;
102 /*FIXME later, the loop file should
103 *be different for different system*/
105 sprintf(name, "/dev/loop/%d", i);
107 if (path_init(name, LOOKUP_FOLLOW, &nd)) {
108 error = path_walk(name, &nd);
111 SM_FREE(name, sizeof(name) + 1);
115 SM_FREE(name, sizeof(name) + 1);
119 bd_ops = get_blkfops(LOOP_MAJOR);
120 error = bd_ops->ioctl(dentry->d_inode,
125 filp_close(filp, current->files);
131 SM_ALLOC(name, strlen(dev_path) + 1);
132 memcpy(name, dev_path, strlen(dev_path) + 1);
133 filp_close(filp, current->files);
136 extern struct super_operations smfs_super_ops;
138 static int sm_mount_cache(struct super_block *sb,
142 struct vfsmount *mnt;
143 struct smfs_super_info *smb;
144 char *dev_name = NULL;
148 dev_name = parse_path2dev(sb, devstr);
150 GOTO(err_out, err = -ENOMEM);
152 if (!(page = __get_free_page(GFP_KERNEL))) {
153 GOTO(err_out, err = -ENOMEM);
155 memset((void *)page, 0, PAGE_SIZE);
156 sprintf((char *)page, "iopen_nopriv");
158 mnt = do_kern_mount(typestr, 0, dev_name, (void *)page);
162 CERROR("do_kern_mount failed: rc = %d\n", err);
166 smb->smsi_sb = mnt->mnt_sb;
168 sm_set_sb_ops(mnt->mnt_sb, sb);
171 SM_FREE(dev_name, strlen(dev_name) + 2);
175 static int sm_umount_cache(struct super_block *sb)
177 struct smfs_super_info *smb = S2SMI(sb);
179 mntput(smb->smsi_mnt);
182 void smfs_put_super(struct super_block *sb)
191 struct super_block *sb,
195 struct smfs_inode_info *smi;
196 struct dentry *bottom_root;
197 struct inode *root_inode = NULL;
198 char *devstr = NULL, *typestr = NULL;
205 CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
208 /* read and validate options */
209 cache_data = smfs_options(data, &devstr, &typestr);
211 CERROR("invalid mount option %s\n", (char*)data);
212 GOTO(out_err, err=-EINVAL);
214 if (!typestr || !devstr) {
215 CERROR("mount options name and dev mandatory\n");
216 GOTO(out_err, err=-EINVAL);
219 err = sm_mount_cache(sb, devstr, typestr);
221 CERROR("Can not mount %s as %s\n", devstr, typestr);
224 /* set up the super block */
226 bottom_root = dget(S2SMI(sb)->smsi_sb->s_root);
228 CERROR("bottom not mounted\n");
229 GOTO(out_err, err=-ENOENT);
232 root_ino = bottom_root->d_inode->i_ino;
233 smi = I2SMI(root_inode);
234 /*FIXME Intialize smi here*/
236 CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
237 sb->s_op->read_inode, root_ino, root_inode);
239 sb->s_root = d_alloc_root(bottom_root->d_inode);
242 GOTO(out_err, err=-EINVAL);
245 CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
246 (ulong) sb, (ulong) &sb->u.generic_sbp);
255 static DECLARE_FSTYPE(smfs_type, "smfs", smfs_read_super, 0);
261 err = register_filesystem(&smfs_type);
263 CERROR("smfs: failed in register Storage Management filesystem!\n");
269 int cleanup_smfs(void)
274 err = unregister_filesystem(&smfs_type);
276 CERROR("smfs: failed to unregister Storage Management filesystem!\n");
278 cleanup_smfs_cache();