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 <linux/lustre_idl.h>
26 #include "smfs_internal.h"
28 /* Find the options for the clone. These consist of a cache device
29 and an index in the snaptable associated with that device.
31 static char *smfs_options(char *options, char **devstr, char **namestr, int *kml)
33 struct option *opt_value = NULL;
36 while (!(get_opt(&opt_value, &pos))) {
37 if (!strcmp(opt_value->opt, "dev")) {
39 *devstr = opt_value->value;
40 } else if (!strcmp(opt_value->opt, "type")) {
42 *namestr = opt_value->value;
43 } else if (!strcmp(opt_value->opt, "kml")) {
52 static int set_loop_fd(char *dev_path, char *loop_dev)
54 struct loop_info loopinfo;
56 struct dentry *dentry;
57 struct block_device_operations *bd_ops;
59 int fd = 0, error = 0;
63 if (!fd) RETURN(-EINVAL);
65 filp = filp_open(dev_path, FMODE_WRITE, 0);
66 if (!filp || !S_ISREG(filp->f_dentry->d_inode->i_mode))
71 if (path_init(loop_dev, LOOKUP_FOLLOW, &nd)) {
72 error = path_walk(loop_dev, &nd);
75 filp_close(filp, current->files);
80 filp_close(filp, current->files);
84 bd_ops = get_blkfops(LOOP_MAJOR);
86 error = bd_ops->ioctl(dentry->d_inode, filp, LOOP_SET_FD,
90 filp_close(filp, current->files);
93 memset(&loopinfo, 0, sizeof(struct loop_info));
95 error = bd_ops->ioctl(dentry->d_inode, filp, LOOP_SET_STATUS,
96 (unsigned long)(&loopinfo));
101 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
102 static char *find_unused_and_set_loop_device(char *dev_path)
104 char *loop_formats[] = { "/dev/loop/%d", "/dev/loop%d"};
105 struct loop_info loopinfo;
107 struct dentry *dentry;
111 for (j = 0; j < SIZE(loop_formats); j++) {
112 SM_ALLOC(dev, strlen(loop_formats[i]) + 1);
113 for(i = 0; i < 256; i++) {
114 struct block_device_operations *bd_ops;
116 sprintf(dev, loop_formats[j], i);
118 if (path_init(dev, LOOKUP_FOLLOW, &nd)) {
119 error = path_walk(dev, &nd);
120 if (error && error != -ENOENT) {
122 SM_FREE(dev, strlen(loop_formats[i]) + 1);
126 SM_FREE(dev, strlen(loop_formats[i]) + 1);
130 bd_ops = get_blkfops(LOOP_MAJOR);
131 error = bd_ops->ioctl(dentry->d_inode, NULL, LOOP_GET_STATUS,
132 (unsigned long)&loopinfo);
135 if (error == -ENXIO) {
136 /*find unused loop and set dev_path to loopdev*/
137 error = set_loop_fd(dev_path, dev);
139 SM_FREE(dev, strlen(loop_formats[i]) + 1);
142 return dev;/* probably free */
145 SM_FREE(dev, strlen(loop_formats[i]) + 1);
150 #define MAX_LOOP_DEVICES 256
151 static char *parse_path2dev(struct super_block *sb, char *dev_path)
153 struct dentry *dentry;
158 if (path_init(dev_path, LOOKUP_FOLLOW, &nd)) {
159 error = path_walk(dev_path, &nd);
169 if (!dentry->d_inode || is_bad_inode(dentry->d_inode) ||
170 (!S_ISBLK(dentry->d_inode->i_mode) &&
171 !S_ISREG(dentry->d_inode->i_mode))){
176 if (S_ISREG(dentry->d_inode->i_mode)) {
177 name = find_unused_and_set_loop_device(dev_path);
181 SM_ALLOC(name, strlen(dev_path) + 1);
182 memcpy(name, dev_path, strlen(dev_path) + 1);
185 void duplicate_sb(struct super_block *csb,
186 struct super_block *sb)
188 sb->s_blocksize = csb->s_blocksize;
189 sb->s_magic = csb->s_magic;
190 sb->s_blocksize_bits = csb->s_blocksize_bits;
191 sb->s_maxbytes = csb->s_maxbytes;
193 extern struct super_operations smfs_super_ops;
195 static int sm_mount_cache(struct super_block *sb,
199 struct vfsmount *mnt;
200 struct smfs_super_info *smb;
201 char *dev_name = NULL;
205 dev_name = parse_path2dev(sb, devstr);
207 GOTO(err_out, err = -ENOMEM);
209 if (!(page = __get_free_page(GFP_KERNEL))) {
210 GOTO(err_out, err = -ENOMEM);
212 memset((void *)page, 0, PAGE_SIZE);
213 sprintf((char *)page, "iopen_nopriv");
215 mnt = do_kern_mount(typestr, 0, dev_name, (void *)page);
219 CERROR("do_kern_mount failed: rc = %ld\n", PTR_ERR(mnt));
220 GOTO(err_out, err = PTR_ERR(mnt));
223 smb->smsi_sb = mnt->mnt_sb;
226 duplicate_sb(mnt->mnt_sb, sb);
227 sm_set_sb_ops(mnt->mnt_sb, sb);
230 SM_FREE(dev_name, strlen(dev_name) + 2);
234 static int sm_umount_cache(struct super_block *sb)
236 struct smfs_super_info *smb = S2SMI(sb);
238 mntput(smb->smsi_mnt);
242 void smfs_put_super(struct super_block *sb)
251 struct super_block *sb,
255 struct inode *root_inode = NULL;
256 char *devstr = NULL, *typestr = NULL;
259 int err = 0, kml = 0;
263 CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
266 /* read and validate options */
267 cache_data = smfs_options(data, &devstr, &typestr, &kml);
269 CERROR("invalid mount option %s\n", (char*)data);
270 GOTO(out_err, err=-EINVAL);
272 if (!typestr || !devstr) {
273 CERROR("mount options name and dev mandatory\n");
274 GOTO(out_err, err=-EINVAL);
277 err = sm_mount_cache(sb, devstr, typestr);
279 CERROR("Can not mount %s as %s\n", devstr, typestr);
283 if (kml) smfs_kml_init(sb);
285 setup_sm_journal_ops(typestr);
287 dget(S2CSB(sb)->s_root);
288 root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
289 root_inode = iget(sb, root_ino);
291 CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
292 sb->s_op->read_inode, root_ino, root_inode);
294 sb->s_root = d_alloc_root(root_inode);
297 GOTO(out_err, err=-EINVAL);
300 CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
301 (ulong) sb, (ulong) &sb->u.generic_sbp);
310 static DECLARE_FSTYPE(smfs_type, "smfs", smfs_read_super, 0);
316 err = register_filesystem(&smfs_type);
318 CERROR("smfs: failed in register Storage Management filesystem!\n");
324 int cleanup_smfs(void)
329 err = unregister_filesystem(&smfs_type);
331 CERROR("smfs: failed to unregister Storage Management filesystem!\n");
333 cleanup_smfs_cache();