1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2004 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #define DEBUG_SUBSYSTEM S_SM
25 #include <linux/config.h>
26 #include <linux/module.h>
27 #include <linux/kmod.h>
28 #include <linux/init.h>
30 #include <linux/string.h>
32 #include <linux/utime.h>
33 #include <linux/file.h>
34 #include <linux/slab.h>
35 #include <linux/dcache.h>
36 #include <linux/loop.h>
37 #include <linux/errno.h>
38 #include <linux/obd_class.h>
39 #include <linux/obd_support.h>
40 #include <linux/lustre_lib.h>
41 #include <linux/lustre_idl.h>
42 #include <linux/lustre_fsfilt.h>
43 #include <linux/lustre_smfs.h>
44 #include "smfs_internal.h"
46 static char *smfs_options(char *data, char **devstr, char **namestr,
47 int *kml, int *cache, char **opts,
51 struct option *opt_value = NULL;
53 while (!(get_opt(&opt_value, &pos))) {
54 if (!strcmp(opt_value->opt, "dev")) {
56 *devstr = opt_value->value;
57 } else if (!strcmp(opt_value->opt, "type")) {
59 *namestr = opt_value->value;
60 } else if (!strcmp(opt_value->opt, "kml")) {
63 } else if (!strcmp(opt_value->opt, "cache")) {
66 } else if (!strcmp(opt_value->opt, "options")) {
68 *opts = opt_value->value;
69 } else if (!strcmp(opt_value->opt, "iopen_nopriv")) {
70 if (iopen_nopriv != NULL)
79 struct vfsmount *get_vfsmount(struct super_block *sb)
81 struct vfsmount *rootmnt, *mnt, *ret = NULL;
82 struct list_head *end, *list;
84 rootmnt = mntget(current->fs->rootmnt);
85 end = list = &rootmnt->mnt_list;
87 mnt = list_entry(list, struct vfsmount, mnt_list);
88 if (mnt->mnt_sb == sb) {
93 } while (end != list);
95 mntput(current->fs->rootmnt);
99 struct super_block *smfs_get_sb_by_path(char *path, int len)
101 struct super_block *sb;
107 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
108 if (path_init(path, LOOKUP_FOLLOW, &nd)) {
110 if (path_lookup(path, LOOKUP_FOLLOW, &nd)) {
112 error = path_walk(path, &nd);
121 /* FIXME-WANGDI: add some check code here. */
122 sb = nd.dentry->d_sb;
127 static int smfs_init_fsfilt_ops(struct super_block *sb)
130 if (!S2SMI(sb)->sm_cache_fsfilt) {
131 S2SMI(sb)->sm_cache_fsfilt =
132 fsfilt_get_ops(S2SMI(sb)->cache_fs_type);
133 if (!S2SMI(sb)->sm_cache_fsfilt) {
134 CERROR("Can not get %s fsfilt ops needed by kml\n",
135 S2SMI(sb)->cache_fs_type);
139 if (!S2SMI(sb)->sm_fsfilt) {
140 S2SMI(sb)->sm_fsfilt =
141 fsfilt_get_ops(S2SMI(sb)->fs_type);
142 if (!S2SMI(sb)->sm_fsfilt) {
143 CERROR("Can not get %s fsfilt ops needed by kml\n",
151 void smfs_cleanup_fsfilt_ops(struct super_block *sb)
153 if (S2SMI(sb)->sm_cache_fsfilt)
154 fsfilt_put_ops(S2SMI(sb)->sm_cache_fsfilt);
155 if (S2SMI(sb)->sm_fsfilt)
156 fsfilt_put_ops(S2SMI(sb)->sm_fsfilt);
159 static int sm_mount_cache(struct super_block *sb, char *devstr,
160 char *typestr, char *opts, int iopen_nopriv)
162 struct smfs_super_info *smb;
163 int err = 0, typelen;
164 struct vfsmount *mnt;
169 typelen = strlen(typestr);
171 page = __get_free_page(GFP_KERNEL);
173 GOTO(err_out, err = -ENOMEM);
175 memset((void *)page, 0, PAGE_SIZE);
178 sprintf((char *)page, "iopen_nopriv");
180 if (opts && strlen(opts)) {
181 int n = strlen((char *)page);
182 sprintf((char *)page + n, ",%s", opts);
185 printk("smfs: mounting %s at %s\n", typestr, devstr);
187 mnt = do_kern_mount(typestr, 0, devstr, (void *)page);
191 CERROR("do_kern_mount failed: rc = %ld\n", PTR_ERR(mnt));
192 GOTO(err_out, err = PTR_ERR(mnt));
195 smb->smsi_sb = mnt->mnt_sb;
198 smfs_init_sm_ops(smb);
200 OBD_ALLOC(smb->cache_fs_type, strlen(typestr) + 1);
201 memcpy(smb->cache_fs_type, typestr, strlen(typestr));
203 OBD_ALLOC(smb->fs_type, strlen(SMFS_TYPE) + 1);
204 memcpy(smb->fs_type, SMFS_TYPE, strlen(SMFS_TYPE));
206 duplicate_sb(sb, mnt->mnt_sb);
207 sm_set_sb_ops(mnt->mnt_sb, sb);
208 err = smfs_init_fsfilt_ops(sb);
213 static int sm_umount_cache(struct super_block *sb)
215 struct smfs_super_info *smb = S2SMI(sb);
217 mntput(smb->smsi_mnt);
218 smfs_cleanup_sm_ops(smb);
219 smfs_cleanup_fsfilt_ops(sb);
221 if (smb->cache_fs_type)
222 OBD_FREE(smb->cache_fs_type, strlen(smb->cache_fs_type) + 1);
225 OBD_FREE(smb->fs_type, strlen(smb->fs_type) + 1);
230 void smfs_put_super(struct super_block *sb)
232 if (SMFS_CACHE_HOOK(S2SMI(sb)))
233 cache_space_hook_exit(sb);
235 if (SMFS_DO_REC(S2SMI(sb)))
236 smfs_rec_cleanup(sb);
243 static int smfs_fill_super(struct super_block *sb,
244 void *data, int silent)
249 int iopen_nopriv = 0;
250 struct inode *root_inode = NULL;
251 int err = 0, do_rec = 0, cache_hook = 0;
252 char *devstr = NULL, *typestr = NULL, *opts = NULL;
256 CDEBUG(D_SUPER, "mount opts: %s\n", data ?
257 (char *)data : "(none)");
261 /* read and validate passed options. */
262 cache_data = smfs_options(data, &devstr, &typestr,
263 &do_rec, &cache_hook, &opts,
267 CWARN("smfs_fill_super(): options parsing stoped at "
268 "option %s\n", cache_data);
270 if (!typestr || !devstr) {
271 CERROR("mount options name and dev mandatory\n");
272 GOTO(out_err, err = -EINVAL);
275 err = sm_mount_cache(sb, devstr, typestr, opts,
279 CERROR("Can not mount %s as %s, rc = %d\n", devstr,
288 cache_space_hook_init(sb);
290 dget(S2CSB(sb)->s_root);
291 root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
292 root_inode = iget(sb, root_ino);
294 CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
295 sb->s_op->read_inode, root_ino, root_inode);
297 sb->s_root = d_alloc_root(root_inode);
301 GOTO(out_err, err = -EINVAL);
304 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
305 CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
306 (ulong)sb, (ulong)&sb->u.generic_sbp);
308 CDEBUG(D_SUPER, "sb %lx, &sb->s_fs_info: %lx\n",
309 (ulong)sb, (ulong)&sb->s_fs_info);
317 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
318 static struct super_block *smfs_read_super(struct super_block *sb,
319 void *data, int silent)
323 err = smfs_fill_super(sb, data, silent);
330 struct super_block *smfs_get_sb(struct file_system_type *fs_type,
331 int flags, const char *dev_name,
334 return get_sb_nodev(fs_type, flags, data, smfs_fill_super);
338 static struct file_system_type smfs_type = {
339 .owner = THIS_MODULE,
341 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
342 .read_super = smfs_read_super,
344 .get_sb = smfs_get_sb,
345 .kill_sb = kill_anon_super,
353 err = register_filesystem(&smfs_type);
355 CERROR("register_filesystem() failed, "
361 int cleanup_smfs(void)
365 err = unregister_filesystem(&smfs_type);
367 CERROR("unregister_filesystem() failed, "