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, "audit")) {
84 SMFS_SET(*flags, SMFS_PLG_AUDIT);
85 } else if (!strcmp(pos, "cache")) {
86 SMFS_SET(*flags, SMFS_PLG_LRU);
87 } else if (!strcmp(pos, "snap")) {
88 SMFS_SET(*flags, SMFS_PLG_COW);
90 /* So it is wrong or backfs option,
102 //save dev & type for further use
104 *devstr = strcpy(ret + strlen(ret) + 1, *devstr);
106 *namestr = strcpy(*devstr + strlen(*devstr) + 1, *namestr);
108 OBD_FREE(temp, strlen(data) + 1);
113 static struct smfs_super_info *smfs_init_smb(struct super_block *sb)
115 struct smfs_super_info *smb;
118 OBD_ALLOC(smb, sizeof(*smb));
123 INIT_LIST_HEAD(&smb->smsi_plg_list);
128 static void smfs_cleanup_smb(struct smfs_super_info *smb)
133 OBD_FREE(smb, sizeof(*smb));
137 static int smfs_init_fsfilt_ops(struct smfs_super_info *smb)
140 if (!smb->sm_cache_fsfilt) {
141 smb->sm_cache_fsfilt =
142 fsfilt_get_ops(smb->smsi_cache_ftype);
143 if (!smb->sm_cache_fsfilt) {
144 CERROR("Can not get %s fsfilt ops needed by smfs\n",
145 smb->smsi_cache_ftype);
149 if (!smb->sm_fsfilt) {
151 fsfilt_get_ops(smb->smsi_ftype);
152 if (!smb->sm_fsfilt) {
153 CERROR("Can not get %s fsfilt ops needed by smfs\n",
161 void smfs_cleanup_fsfilt_ops(struct smfs_super_info *smb)
163 if (smb->sm_cache_fsfilt)
164 fsfilt_put_ops(smb->sm_cache_fsfilt);
166 fsfilt_put_ops(smb->sm_fsfilt);
169 static void smfs_filter_flags(struct filter_obd *filt, struct inode *o_dir)
171 struct dentry * dentry = NULL;
174 CDEBUG(D_SUPER,"OST OBD post_setup\n");
176 /* enable plugins for all in O */
177 /* SMFS_SET(I2SMI(o_dir)->smi_flags, SMFS_PLG_ALL); */
179 /* enable plugins for all already created d<n> dirs */
180 for (j = 1; j < filt->fo_group_count; j++) {
181 for (i = 0; i < filt->fo_subdir_count; i++) {
182 dentry = (filt->fo_subdirs + j)->dentry[i];
183 SMFS_SET(I2SMI(dentry->d_inode)->smi_flags,
189 static void smfs_mds_flags(struct mds_obd *mds, struct inode *root)
191 CDEBUG(D_SUPER,"MDS OBD post_setup\n");
193 /* enable plugins for all in ROOT */
194 SMFS_SET(I2SMI(root)->smi_flags, SMFS_PLG_ALL);
195 SMFS_SET(I2SMI(mds->mds_unnamed_dir->d_inode)->smi_flags, SMFS_PLG_ALL);
198 extern int (*audit_id2name_superhack) (struct obd_device *obd, char **name,
199 int *namelen, struct lustre_id *id);
201 int smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt,
202 struct dentry *root_dentry)
204 struct lvfs_run_ctxt saved, *current_ctxt = NULL;
205 struct smfs_super_info *smb = S2SMI(mnt->mnt_sb);
209 /* XXX to register id2name function of mds in smfs */
211 // audit_id2name_superhack = data;
213 OBD_ALLOC(current_ctxt, sizeof(*current_ctxt));
217 OBD_SET_CTXT_MAGIC(current_ctxt);
219 current_ctxt->pwdmnt = mnt;
220 current_ctxt->pwd = mnt->mnt_root;
221 current_ctxt->fs = get_ds();
222 smb->smsi_ctxt = current_ctxt;
224 push_ctxt(&saved, smb->smsi_ctxt, NULL);
226 rc = smfs_llog_setup(&smb->smsi_logs_dir, &smb->smsi_objects_dir);
228 rc = SMFS_PLG_HELP(mnt->mnt_sb, PLG_START, obd);
230 pop_ctxt(&saved, smb->smsi_ctxt, NULL);
232 /* enable plugins for directories on MDS or OST */
233 if (obd && obd->obd_type && obd->obd_type->typ_name) {
234 if (!strcmp(obd->obd_type->typ_name, OBD_FILTER_DEVICENAME)) {
235 struct filter_obd *filt = &obd->u.filter;
236 smfs_filter_flags(filt, root_dentry->d_inode);
237 } else if (!strcmp(obd->obd_type->typ_name, OBD_MDS_DEVICENAME)) {
238 struct mds_obd * mds = &obd->u.mds;
239 smfs_mds_flags(mds, root_dentry->d_inode);
240 SMFS_SET_HND_IBLOCKS(smb);
242 CDEBUG(D_SUPER,"Unknown OBD (%s) post_setup\n",
243 obd->obd_type->typ_name);
248 OBD_FREE(current_ctxt, sizeof(*current_ctxt));
253 void smfs_post_cleanup(struct super_block *sb)
255 struct smfs_super_info *smb = S2SMI(sb);
259 smfs_llog_cleanup(smb);
260 SMFS_PLG_HELP(sb, PLG_STOP, NULL);
263 OBD_FREE(smb->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
268 static int smfs_mount_cache(struct smfs_super_info *smb, char *devstr,
269 char *typestr, char *opts)
271 int err = 0, typelen;
272 struct vfsmount *mnt;
275 typelen = strlen(typestr);
277 CDEBUG(D_INODE, "smfs: mounting %s at %s\n", typestr, devstr);
279 mnt = do_kern_mount(typestr, 0, devstr, (void *)opts);
281 CERROR("do_kern_mount failed: rc = %d\n",
283 RETURN(PTR_ERR(mnt));
286 smb->smsi_sb = mnt->mnt_sb;
289 smfs_init_sm_ops(smb);
291 OBD_ALLOC(smb->smsi_cache_ftype, strlen(typestr) + 1);
292 if (!smb->smsi_cache_ftype)
293 GOTO(err_umount_cache, err = -ENOMEM);
295 memcpy(smb->smsi_cache_ftype, typestr, strlen(typestr));
297 OBD_ALLOC(smb->smsi_ftype, strlen(SMFS_TYPE) + 1);
298 if (!smb->smsi_ftype)
299 GOTO(err_free_cache_fstype, err = -ENOMEM);
301 memcpy(smb->smsi_ftype, SMFS_TYPE, strlen(SMFS_TYPE));
303 err = smfs_init_fsfilt_ops(smb);
305 err_free_cache_fstype:
306 OBD_FREE(smb->smsi_cache_ftype, strlen(typestr) + 1);
312 static int smfs_umount_cache(struct smfs_super_info *smb)
316 mntput(smb->smsi_mnt);
317 smfs_cleanup_sm_ops(smb);
318 smfs_cleanup_fsfilt_ops(smb);
320 if (smb->smsi_cache_ftype) {
321 OBD_FREE(smb->smsi_cache_ftype,
322 strlen(smb->smsi_cache_ftype) + 1);
323 smb->smsi_cache_ftype = NULL;
325 if (smb->smsi_ftype) {
326 OBD_FREE(smb->smsi_ftype,
327 strlen(smb->smsi_ftype) + 1);
328 smb->smsi_ftype = NULL;
334 /* This function initializes plugins in SMFS
335 * @flags: are filled while options parsing
336 * @sb: smfs super block
338 static int smfs_init_plugins(struct super_block * sb, int flags)
340 struct smfs_super_info * smb = S2SMI(sb);
344 INIT_LIST_HEAD(&smb->smsi_plg_list);
345 init_rwsem(&smb->plg_sem);
347 if (SMFS_IS(flags, SMFS_PLG_AUDIT))
349 if (SMFS_IS(flags, SMFS_PLG_KML))
351 if (SMFS_IS(flags, SMFS_PLG_LRU))
354 if (SMFS_IS(flags, SMFS_PLG_COW))
360 static void smfs_remove_plugins(struct super_block *sb)
362 struct smfs_plugin * plg, *tmp;
363 struct smfs_super_info *smb = S2SMI(sb);
364 struct list_head * plist = &smb->smsi_plg_list;
368 list_for_each_entry_safe(plg, tmp, plist, plg_list) {
369 plg->plg_exit(sb, plg->plg_private);
375 void smfs_put_super(struct super_block *sb)
377 struct smfs_super_info *smb = S2SMI(sb);
379 smfs_remove_plugins(sb);
384 smfs_umount_cache(smb);
386 smfs_cleanup_smb(smb);
390 int smfs_fill_super(struct super_block *sb, void *data, int silent)
392 struct inode *root_inode = NULL;
393 struct inode *back_root_inode = NULL;
394 struct smfs_super_info *smb = NULL;
395 char *devstr = NULL, *typestr = NULL;
396 unsigned long page = 0;
404 CERROR("no mount options. At least name and dev are needed\n");
409 CDEBUG(D_SUPER, "mount opts: %s\n", (char *)data);
411 smb = smfs_init_smb(sb);
417 /* 2.6.9 selinux wants a full option page for do_kern_mount (bug6471) */
418 page = get_zeroed_page(GFP_KERNEL);
425 err = smfs_options(data, &devstr, &typestr, opts, &flags);
429 if (!typestr || !devstr) {
430 CERROR("mount options name and dev are mandatory\n");
435 CDEBUG(D_SUPER, "backfs mount opts: %s\n", opts);
437 err = smfs_mount_cache(smb, devstr, typestr, opts);
439 CERROR("Can not mount %s as %s\n", devstr, typestr);
446 duplicate_sb(sb, smb->smsi_sb);
447 sb->s_bdev = smb->smsi_sb->s_bdev;
448 sm_set_sb_ops(smb->smsi_sb, sb);
450 /* init the root_inode of smfs. */
451 back_root_inode = S2CSB(sb)->s_root->d_inode;
452 root_inode = smfs_get_inode(sb, back_root_inode, NULL, 0);
454 CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
455 sb->s_op->read_inode, root_inode->i_ino, root_inode);
457 sb->s_root = d_alloc_root(root_inode);
463 /* all entries created until post_setup() should not be logged */
464 SMFS_CLEAR((I2SMI(root_inode))->smi_flags, SMFS_PLG_ALL);
466 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
467 CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
468 (ulong)sb, (ulong)&sb->u.generic_sbp);
470 CDEBUG(D_SUPER, "sb %lx(%p), &sb->s_fs_info: %lx\n",
471 (ulong)sb, smb->smsi_sb, (ulong)&sb->s_fs_info);
474 smfs_init_plugins(sb, flags);
479 smfs_umount_cache(smb);
484 smfs_cleanup_smb(smb);
489 void *smfs_trans_start(struct inode *inode, int op, void *desc_private)
491 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
493 if (fsfilt->fs_start)
494 return fsfilt->fs_start(inode, op, NULL, 0);
498 void smfs_trans_commit(struct inode *inode, void *handle, int force_sync)
500 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
502 if (handle && fsfilt->fs_commit)
503 fsfilt->fs_commit(inode->i_sb, inode, handle, force_sync);
506 int smfs_register_plugin(struct super_block * sb,
507 struct smfs_plugin * plg)
509 struct smfs_plugin * tmp = NULL;
510 struct smfs_super_info * smb = S2SMI(sb);
511 struct list_head * plist = &smb->smsi_plg_list;
516 down_write(&smb->plg_sem);
517 list_for_each_entry(tmp, plist, plg_list) {
518 if (tmp->plg_type == plg->plg_type) {
519 CWARN("Plugin is already registered\n");
525 list_add_tail(&plg->plg_list, plist);
527 up_write(&smb->plg_sem);
531 struct smfs_plugin * smfs_deregister_plugin(struct super_block *sb, int type)
533 struct smfs_plugin * plg = NULL;
534 struct smfs_super_info *smb = S2SMI(sb);
535 struct list_head * plist = &smb->smsi_plg_list;
538 down_write(&smb->plg_sem);
539 list_for_each_entry(plg, plist, plg_list) {
540 if (plg->plg_type == type) {
541 list_del(&plg->plg_list);
545 up_write(&smb->plg_sem);
549 void smfs_pre_hook (struct inode * inode, hook_op op, void * msg)
551 struct smfs_super_info *smb = S2SMI(inode->i_sb);
552 struct smfs_inode_info *smi = I2SMI(inode);
553 struct list_head *hlist = &smb->smsi_plg_list;
554 struct smfs_plugin *plg;
557 LASSERT(op < HOOK_MAX);
558 //call hook operations
559 down_read(&smb->plg_sem);
560 list_for_each_entry(plg, hlist, plg_list) {
561 //check that plugin is active
562 if(!SMFS_IS(smb->plg_flags, plg->plg_type))
564 //check that inode is allowed
565 if (!SMFS_IS(smi->smi_flags, plg->plg_type))
569 plg->plg_pre_op(op, inode, msg, 0, plg->plg_private);
571 up_read(&smb->plg_sem);
575 void smfs_post_hook (struct inode * inode, hook_op op, void * msg, int ret)
577 struct smfs_super_info *smb = S2SMI(inode->i_sb);
578 //struct smfs_inode_info *smi = I2SMI(inode);
579 struct list_head *hlist = &smb->smsi_plg_list;
580 struct smfs_plugin *plg;
583 down_read(&smb->plg_sem);
584 list_for_each_entry(plg, hlist, plg_list) {
585 //check that plugin is active
586 if(!SMFS_IS(smb->plg_flags, plg->plg_type))
588 /* this will be checked inside plg_post_op()
589 if (!SMFS_IS(smi->smi_flags, plg->plg_type))
592 if (plg->plg_post_op)
593 plg->plg_post_op(op, inode, msg, ret, plg->plg_private);
595 up_read(&smb->plg_sem);
599 int smfs_helper (struct super_block * sb, int op, void * msg)
601 struct smfs_super_info *smb = S2SMI(sb);
602 struct list_head *hlist = &smb->smsi_plg_list;
603 struct smfs_plugin *plg, *tmp;
607 LASSERT(op < PLG_HELPER_MAX);
608 //call hook operations
609 down_read(&smb->plg_sem);
610 list_for_each_entry_safe(plg, tmp, hlist, plg_list) {
611 //check that plugin is active
612 if(!SMFS_IS(smb->plg_flags, plg->plg_type) &&
613 !(op == PLG_START || op == PLG_EXIT))
617 rc += plg->plg_helper(op, sb, msg, plg->plg_private);
619 up_read(&smb->plg_sem);
625 void * smfs_get_plg_priv(struct smfs_super_info * smb, int type)
627 struct list_head *hlist = &smb->smsi_plg_list;
628 struct smfs_plugin *plg, *tmp;
630 list_for_each_entry_safe(plg, tmp, hlist, plg_list) {
631 if (plg->plg_type == type) {
632 return (plg->plg_private);