1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 * Lustre filesystem abstraction routines
7 * Copyright (C) 2004 Cluster File Systems, Inc.
9 * This file is part of Lustre, http://www.lustre.org.
11 * Lustre is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU General Public
13 * License as published by the Free Software Foundation.
15 * Lustre is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with Lustre; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #define DEBUG_SUBSYSTEM S_SM
27 #include <linux/config.h>
28 #include <linux/module.h>
29 #include <linux/kmod.h>
30 #include <linux/init.h>
32 #include <linux/string.h>
34 #include <linux/utime.h>
35 #include <linux/file.h>
36 #include <linux/slab.h>
37 #include <linux/dcache.h>
38 #include <linux/loop.h>
39 #include <linux/errno.h>
40 #include <linux/obd_class.h>
41 #include <linux/obd_support.h>
42 #include <linux/lustre_lib.h>
43 #include <linux/lustre_idl.h>
44 #include <linux/lustre_fsfilt.h>
45 #include <linux/lustre_smfs.h>
46 #include "smfs_internal.h"
48 int smfs_options(char *data, char **devstr, char **namestr,
49 char *ret, int *flags)
52 char * pos = NULL, *next = NULL;
57 //allocate temporary buffer
58 OBD_ALLOC(temp, strlen(data) + 1);
60 CERROR("Can not allocate memory for options\n");
64 memcpy(temp, data, strlen(data));
68 next = strchr(pos, ',');
74 //now pos points to one-options string
75 if (!strncmp(pos, "dev=", 4)) {
78 } else if (!strncmp(pos, "type=", 5)) {
81 } else if (!strcmp(pos, "kml")) {
82 SMFS_SET(*flags, SMFS_PLG_KML);
83 } else if (!strcmp(pos, "cache")) {
84 SMFS_SET(*flags, SMFS_PLG_LRU);
85 } else if (!strcmp(pos, "snap")) {
86 SMFS_SET(*flags, SMFS_PLG_COW);
88 /* So it is wrong or backfs option,
100 //save dev & type for further use
102 *devstr = strcpy(ret + strlen(ret) + 1, *devstr);
104 *namestr = strcpy(*devstr + strlen(*devstr) + 1, *namestr);
106 OBD_FREE(temp, strlen(data) + 1);
111 static struct smfs_super_info *smfs_init_smb(struct super_block *sb)
113 struct smfs_super_info *smb;
116 OBD_ALLOC(smb, sizeof(*smb));
124 static void smfs_cleanup_smb(struct smfs_super_info *smb)
129 OBD_FREE(smb, sizeof(*smb));
133 static int smfs_init_fsfilt_ops(struct smfs_super_info *smb)
136 if (!smb->sm_cache_fsfilt) {
137 smb->sm_cache_fsfilt =
138 fsfilt_get_ops(smb->smsi_cache_ftype);
139 if (!smb->sm_cache_fsfilt) {
140 CERROR("Can not get %s fsfilt ops needed by smfs\n",
141 smb->smsi_cache_ftype);
145 if (!smb->sm_fsfilt) {
147 fsfilt_get_ops(smb->smsi_ftype);
148 if (!smb->sm_fsfilt) {
149 CERROR("Can not get %s fsfilt ops needed by smfs\n",
157 void smfs_cleanup_fsfilt_ops(struct smfs_super_info *smb)
159 if (smb->sm_cache_fsfilt)
160 fsfilt_put_ops(smb->sm_cache_fsfilt);
162 fsfilt_put_ops(smb->sm_fsfilt);
165 int smfs_post_setup(struct super_block *sb, struct vfsmount *mnt)
167 struct lvfs_run_ctxt saved, *current_ctxt = NULL;
168 struct smfs_super_info *smb = S2SMI(sb);
173 OBD_ALLOC(current_ctxt, sizeof(*current_ctxt));
177 OBD_SET_CTXT_MAGIC(current_ctxt);
179 current_ctxt->pwdmnt = mnt;
180 current_ctxt->pwd = mnt->mnt_root;
181 current_ctxt->fs = get_ds();
182 smb->smsi_ctxt = current_ctxt;
184 push_ctxt(&saved, smb->smsi_ctxt, NULL);
186 rc = smfs_llog_setup(sb, mnt);
188 rc = SMFS_PLG_HELP(sb, PLG_START, NULL);
191 pop_ctxt(&saved, smb->smsi_ctxt, NULL);
194 OBD_FREE(current_ctxt, sizeof(*current_ctxt));
199 void smfs_post_cleanup(struct super_block *sb)
201 struct smfs_super_info *smb = S2SMI(sb);
205 smfs_llog_cleanup(sb);
206 SMFS_PLG_HELP(sb, PLG_STOP, NULL);
209 OBD_FREE(smb->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
214 static int smfs_mount_cache(struct smfs_super_info *smb, char *devstr,
215 char *typestr, char *opts)
217 int err = 0, typelen;
218 struct vfsmount *mnt;
221 typelen = strlen(typestr);
223 CDEBUG(D_INODE, "smfs: mounting %s at %s\n", typestr, devstr);
224 mnt = do_kern_mount(typestr, 0, devstr, (void *)opts);
226 CERROR("do_kern_mount failed: rc = %ld\n",
228 GOTO(err_out, err = PTR_ERR(mnt));
231 smb->smsi_sb = mnt->mnt_sb;
234 smfs_init_sm_ops(smb);
236 OBD_ALLOC(smb->smsi_cache_ftype, strlen(typestr) + 1);
237 memcpy(smb->smsi_cache_ftype, typestr, strlen(typestr));
239 OBD_ALLOC(smb->smsi_ftype, strlen(SMFS_TYPE) + 1);
240 memcpy(smb->smsi_ftype, SMFS_TYPE, strlen(SMFS_TYPE));
242 err = smfs_init_fsfilt_ops(smb);
247 static int smfs_umount_cache(struct smfs_super_info *smb)
249 mntput(smb->smsi_mnt);
250 smfs_cleanup_sm_ops(smb);
251 smfs_cleanup_fsfilt_ops(smb);
253 if (smb->smsi_cache_ftype)
254 OBD_FREE(smb->smsi_cache_ftype,
255 strlen(smb->smsi_cache_ftype) + 1);
257 OBD_FREE(smb->smsi_ftype, strlen(smb->smsi_ftype) + 1);
262 /* This function initializes plugins in SMFS
263 * @flags: are filled while options parsing
264 * @sb: smfs super block
267 static int smfs_init_plugins(struct super_block * sb, int flags)
269 struct smfs_super_info * smb = S2SMI(sb);
273 INIT_LIST_HEAD(&smb->smsi_plg_list);
275 if (SMFS_IS(flags, SMFS_PLG_KML))
277 if (SMFS_IS(flags, SMFS_PLG_LRU))
280 if (SMFS_IS(flags, SMFS_PLG_COW))
286 static void smfs_remove_plugins(struct super_block *sb)
290 SMFS_PLG_HELP(sb, PLG_EXIT, (void*)sb);
295 void smfs_put_super(struct super_block *sb)
297 struct smfs_super_info *smb = S2SMI(sb);
299 smfs_remove_plugins(sb);
304 smfs_umount_cache(smb);
306 smfs_cleanup_smb(smb);
310 int smfs_fill_super(struct super_block *sb, void *data, int silent)
312 struct inode *root_inode = NULL;
313 struct smfs_super_info *smb = NULL;
314 char *devstr = NULL, *typestr = NULL;
323 CERROR("no mount options. At least name and dev are needed\n");
328 CDEBUG(D_SUPER, "mount opts: %s\n", (char *)data);
330 smb = smfs_init_smb(sb);
334 OBD_ALLOC(opts, strlen(data) + 1);
340 err = smfs_options(data, &devstr, &typestr, opts, &flags);
344 if (!typestr || !devstr) {
345 CERROR("mount options name and dev are mandatory\n");
350 CDEBUG(D_SUPER, "backfs mount opts: %s\n", opts);
352 err = smfs_mount_cache(smb, devstr, typestr, opts);
354 CERROR("Can not mount %s as %s\n", devstr, typestr);
358 OBD_FREE(opts, strlen(data) + 1);
361 duplicate_sb(sb, smb->smsi_sb);
362 sb->s_bdev = smb->smsi_sb->s_bdev;
363 sm_set_sb_ops(smb->smsi_sb, sb);
365 /* init the root_inode of smfs. */
366 root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
367 root_inode = smfs_get_inode(sb, root_ino, NULL, 0);
369 CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
370 sb->s_op->read_inode, root_ino, root_inode);
372 sb->s_root = d_alloc_root(root_inode);
378 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
379 CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
380 (ulong)sb, (ulong)&sb->u.generic_sbp);
382 CDEBUG(D_SUPER, "sb %lx(%p), &sb->s_fs_info: %lx\n",
383 (ulong)sb, smb->smsi_sb, (ulong)&sb->s_fs_info);
386 smfs_init_plugins(sb, flags);
391 smfs_umount_cache(smb);
394 OBD_FREE(opts, strlen(data) + 1);
396 smfs_cleanup_smb(smb);
401 void *smfs_trans_start(struct inode *inode, int op, void *desc_private)
403 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
405 CDEBUG(D_INFO, "trans start %p\n", fsfilt->fs_start);
407 SMFS_TRANS_OP(inode, op);
409 /* There are some problem here. fs_start in fsfilt is used by lustre
410 * the journal blocks of write rec are not counted in FIXME later */
411 if (fsfilt->fs_start)
412 return fsfilt->fs_start(inode, op, desc_private, 0);
416 void smfs_trans_commit(struct inode *inode, void *handle, int force_sync)
418 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
423 CDEBUG(D_INFO, "trans commit %p\n", fsfilt->fs_commit);
425 if (fsfilt->fs_commit)
426 fsfilt->fs_commit(inode->i_sb, inode, handle, force_sync);
429 int smfs_register_plugin(struct super_block * sb,
430 struct smfs_plugin * new_plugin)
432 struct smfs_super_info * smb = S2SMI(sb);
433 struct smfs_plugin * plg = NULL;
434 struct list_head * plist = &S2SMI(sb)->smsi_plg_list;
438 list_for_each_entry(plg, plist, plg_list) {
439 if (plg->plg_type == new_plugin->plg_type) {
440 CWARN("Plugin is already registered\n");
446 if (SMFS_IS(smb->smsi_flags, new_plugin->plg_type)) {
447 CWARN("Plugin is already registered\n");
451 OBD_ALLOC(plg, sizeof(*plg));
453 CWARN("Cannot allocate memory for plugin\n");
457 memcpy(plg, new_plugin, sizeof(*plg));
458 list_add_tail(&plg->plg_list, plist);
463 void * smfs_deregister_plugin(struct super_block *sb, int type)
465 struct smfs_plugin * plg = NULL;
466 struct list_head * plist = &S2SMI(sb)->smsi_plg_list;
471 list_for_each_entry(plg, plist, plg_list) {
472 if (plg->plg_type == type) {
473 list_del(&plg->plg_list);
474 priv = plg->plg_private;
475 OBD_FREE(plg, sizeof(*plg));
483 void smfs_pre_hook (struct inode * inode, int op, void * msg)
485 struct smfs_super_info *smb = S2SMI(inode->i_sb);
486 struct smfs_inode_info *smi = I2SMI(inode);
487 struct list_head *hlist = &smb->smsi_plg_list;
488 struct smfs_plugin *plg;
491 LASSERT(op < HOOK_MAX);
492 //call hook operations
493 list_for_each_entry(plg, hlist, plg_list) {
494 //check that plugin is active
495 if(!SMFS_IS(smb->plg_flags, plg->plg_type))
497 //check that inode is not exclusion
498 if (!SMFS_IS(smi->smi_flags, plg->plg_type))
502 plg->plg_pre_op(op, inode, msg, 0, plg->plg_private);
508 void smfs_post_hook (struct inode * inode, int op, void * msg, int ret)
510 struct smfs_super_info *smb = S2SMI(inode->i_sb);
511 struct smfs_inode_info *smi = I2SMI(inode);
512 struct list_head *hlist = &smb->smsi_plg_list;
513 struct smfs_plugin *plg;
517 list_for_each_entry(plg, hlist, plg_list) {
518 //check that plugin is active
519 if(!SMFS_IS(smb->plg_flags, plg->plg_type))
521 //check that inode is not exclusion
522 if (!SMFS_IS(smi->smi_flags, plg->plg_type))
525 if (plg->plg_post_op)
526 plg->plg_post_op(op, inode, msg, ret, plg->plg_private);
532 int smfs_helper (struct super_block * sb, int op, void * msg)
534 struct smfs_super_info *smb = S2SMI(sb);
535 struct list_head *hlist = &smb->smsi_plg_list;
536 struct smfs_plugin *plg, *plg_tmp;
540 LASSERT(op < PLG_HELPER_MAX);
541 //call hook operations
542 list_for_each_entry_safe(plg, plg_tmp, hlist, plg_list) {
544 rc += plg->plg_helper(op, sb, msg, plg->plg_private);