#include <linux/lustre_smfs.h>
#include "smfs_internal.h"
+int smfs_options(char *data, char **devstr, char **namestr,
+ char *ret, int *flags)
+{
+ char * temp;
+ char * pos = NULL, *next = NULL;
+
+ ENTRY;
+
+ LASSERT(flags);
+ //allocate temporary buffer
+ OBD_ALLOC(temp, strlen(data) + 1);
+ if (!temp) {
+ CERROR("Can not allocate memory for options\n");
+ RETURN(-ENOMEM);
+ }
+
+ memcpy(temp, data, strlen(data));
+ pos = temp;
+
+ while (pos) {
+ next = strchr(pos, ',');
+ if (next) {
+ *next = '\0';
+ next++;
+ }
+
+ //now pos points to one-options string
+ if (!strncmp(pos, "dev=", 4)) {
+ if (devstr != NULL)
+ *devstr = pos + 4;
+ } else if (!strncmp(pos, "type=", 5)) {
+ if (namestr != NULL)
+ *namestr = pos + 5;
+ } else if (!strcmp(pos, "kml")) {
+ SMFS_SET(*flags, SMFS_PLG_KML);
+ } else if (!strcmp(pos, "audit")) {
+ SMFS_SET(*flags, SMFS_PLG_AUDIT);
+ } else if (!strcmp(pos, "cache")) {
+ SMFS_SET(*flags, SMFS_PLG_LRU);
+ } else if (!strcmp(pos, "snap")) {
+ SMFS_SET(*flags, SMFS_PLG_COW);
+ } else {
+ /* So it is wrong or backfs option,
+ * let's save it
+ */
+ if (strlen(ret))
+ strcat(ret, ",");
+
+ strcat(ret, pos);
+ }
+
+ pos = next;
+ }
-struct list_head smfs_plg_list;
+ //save dev & type for further use
+ if (*devstr)
+ *devstr = strcpy(ret + strlen(ret) + 1, *devstr);
+ if (*namestr)
+ *namestr = strcpy(*devstr + strlen(*devstr) + 1, *namestr);
+
+ OBD_FREE(temp, strlen(data) + 1);
+
+ RETURN(0);
+}
static struct smfs_super_info *smfs_init_smb(struct super_block *sb)
{
RETURN(NULL);
S2FSI(sb) = smb;
+ INIT_LIST_HEAD(&smb->smsi_plg_list);
+
RETURN(smb);
}
+static void smfs_cleanup_smb(struct smfs_super_info *smb)
+{
+ ENTRY;
+
+ if (smb)
+ OBD_FREE(smb, sizeof(*smb));
+ EXIT;
+}
+
static int smfs_init_fsfilt_ops(struct smfs_super_info *smb)
{
ENTRY;
smb->sm_cache_fsfilt =
fsfilt_get_ops(smb->smsi_cache_ftype);
if (!smb->sm_cache_fsfilt) {
- CERROR("Can not get %s fsfilt ops needed by kml\n",
+ CERROR("Can not get %s fsfilt ops needed by smfs\n",
smb->smsi_cache_ftype);
RETURN(-EINVAL);
}
smb->sm_fsfilt =
fsfilt_get_ops(smb->smsi_ftype);
if (!smb->sm_fsfilt) {
- CERROR("Can not get %s fsfilt ops needed by kml\n",
+ CERROR("Can not get %s fsfilt ops needed by smfs\n",
smb->smsi_ftype);
RETURN(-EINVAL);
}
fsfilt_put_ops(smb->sm_fsfilt);
}
+static void smfs_filter_flags(struct filter_obd * filt, struct inode * o_dir)
+{
+ struct dentry * dentry = NULL;
+ int i,j;
+
+ CDEBUG(D_SUPER,"OST OBD post_setup\n");
+ /* enable plugins for all in O */
+ SMFS_SET(I2SMI(o_dir)->smi_flags, SMFS_PLG_ALL);
+ /* enable plugins for all already created d<n> dirs */
+ for (j = 1; j < filt->fo_group_count; j++) {
+ for (i = 0; i < filt->fo_subdir_count; i++) {
+ dentry = (filt->fo_subdirs + j)->dentry[i];
+ SMFS_SET(I2SMI(dentry->d_inode)->smi_flags,
+ SMFS_PLG_ALL);
+ }
+ }
+}
+
+static void smfs_mds_flags(struct mds_obd *mds, struct inode *root)
+{
+ struct inode *pend = mds->mds_pending_dir->d_inode;
+
+ CDEBUG(D_SUPER,"MDS OBD post_setup\n");
+
+ /* enable plugins for all in ROOT */
+ SMFS_SET(I2SMI(root)->smi_flags, SMFS_PLG_ALL);
+
+ /* the same for PENDING */
+ SMFS_SET(I2SMI(pend)->smi_flags, SMFS_PLG_ALL);
+}
+
+extern int (*audit_id2name_superhack) (struct obd_device *obd, char **name,
+ int *namelen, struct lustre_id *id);
+
+int smfs_post_setup(struct obd_device *obd, struct vfsmount *mnt,
+ struct dentry *root_dentry)
+{
+ struct lvfs_run_ctxt saved, *current_ctxt = NULL;
+ struct smfs_super_info *smb = S2SMI(mnt->mnt_sb);
+ int rc = 0;
+ ENTRY;
+
+ /* XXX to register id2name function of mds in smfs */
+ //if (data != NULL)
+ // audit_id2name_superhack = data;
+
+ OBD_ALLOC(current_ctxt, sizeof(*current_ctxt));
+ if (!current_ctxt)
+ RETURN(-ENOMEM);
+
+ OBD_SET_CTXT_MAGIC(current_ctxt);
+
+ current_ctxt->pwdmnt = mnt;
+ current_ctxt->pwd = mnt->mnt_root;
+ current_ctxt->fs = get_ds();
+ smb->smsi_ctxt = current_ctxt;
+
+ push_ctxt(&saved, smb->smsi_ctxt, NULL);
+
+ rc = smfs_llog_setup(&smb->smsi_logs_dir, &smb->smsi_objects_dir);
+ if (!rc)
+ rc = SMFS_PLG_HELP(mnt->mnt_sb, PLG_START, obd);
+
+ pop_ctxt(&saved, smb->smsi_ctxt, NULL);
+
+ /* enable plugins for directories on MDS or OST */
+ if (obd && obd->obd_type && obd->obd_type->typ_name) {
+ if (!strcmp(obd->obd_type->typ_name, OBD_FILTER_DEVICENAME)) {
+ struct filter_obd *filt = &obd->u.filter;
+ smfs_filter_flags(filt, root_dentry->d_inode);
+ } else if (!strcmp(obd->obd_type->typ_name, OBD_MDS_DEVICENAME)) {
+ struct mds_obd * mds = &obd->u.mds;
+ smfs_mds_flags(mds, root_dentry->d_inode);
+ SMFS_SET_HND_IBLOCKS(smb);
+ } else {
+ CDEBUG(D_SUPER,"Unknown OBD (%s) post_setup\n",
+ obd->obd_type->typ_name);
+ }
+ }
+
+ if (rc)
+ OBD_FREE(current_ctxt, sizeof(*current_ctxt));
+
+ RETURN(rc);
+}
+
+void smfs_post_cleanup(struct super_block *sb)
+{
+ struct smfs_super_info *smb = S2SMI(sb);
+
+ ENTRY;
+
+ smfs_llog_cleanup(smb);
+ SMFS_PLG_HELP(sb, PLG_STOP, NULL);
+
+ if (smb->smsi_ctxt)
+ OBD_FREE(smb->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
+
+ EXIT;
+}
+
static int smfs_mount_cache(struct smfs_super_info *smb, char *devstr,
char *typestr, char *opts)
{
typelen = strlen(typestr);
- printk("smfs: mounting %s at %s\n", typestr, devstr);
+ CDEBUG(D_INODE, "smfs: mounting %s at %s\n", typestr, devstr);
+
mnt = do_kern_mount(typestr, 0, devstr, (void *)opts);
if (IS_ERR(mnt)) {
- CERROR("do_kern_mount failed: rc = %ld\n",
- PTR_ERR(mnt));
- GOTO(err_out, err = PTR_ERR(mnt));
+ CERROR("do_kern_mount failed: rc = %d\n",
+ (int)PTR_ERR(mnt));
+ RETURN(PTR_ERR(mnt));
}
smb->smsi_sb = mnt->mnt_sb;
smfs_init_sm_ops(smb);
OBD_ALLOC(smb->smsi_cache_ftype, strlen(typestr) + 1);
+ if (!smb->smsi_cache_ftype)
+ GOTO(err_umount_cache, err = -ENOMEM);
+
memcpy(smb->smsi_cache_ftype, typestr, strlen(typestr));
OBD_ALLOC(smb->smsi_ftype, strlen(SMFS_TYPE) + 1);
+ if (!smb->smsi_ftype)
+ GOTO(err_free_cache_fstype, err = -ENOMEM);
+
memcpy(smb->smsi_ftype, SMFS_TYPE, strlen(SMFS_TYPE));
err = smfs_init_fsfilt_ops(smb);
-err_out:
RETURN(err);
+err_free_cache_fstype:
+ OBD_FREE(smb->smsi_cache_ftype, strlen(typestr) + 1);
+err_umount_cache:
+ mntput(mnt);
+err_out:
+ return err;
}
static int smfs_umount_cache(struct smfs_super_info *smb)
{
+ ENTRY;
+
mntput(smb->smsi_mnt);
smfs_cleanup_sm_ops(smb);
smfs_cleanup_fsfilt_ops(smb);
- if (smb->smsi_cache_ftype)
+ if (smb->smsi_cache_ftype) {
OBD_FREE(smb->smsi_cache_ftype,
strlen(smb->smsi_cache_ftype) + 1);
- if (smb->smsi_ftype)
- OBD_FREE(smb->smsi_ftype, strlen(smb->smsi_ftype) + 1);
-
- return 0;
+ smb->smsi_cache_ftype = NULL;
+ }
+ if (smb->smsi_ftype) {
+ OBD_FREE(smb->smsi_ftype,
+ strlen(smb->smsi_ftype) + 1);
+ smb->smsi_ftype = NULL;
+ }
+
+ RETURN(0);
}
-static int smfs_init_hook_ops(struct smfs_super_info *smb)
+/* This function initializes plugins in SMFS
+ * @flags: are filled while options parsing
+ * @sb: smfs super block
+ */
+static int smfs_init_plugins(struct super_block * sb, int flags)
{
+ struct smfs_super_info * smb = S2SMI(sb);
+
ENTRY;
- INIT_LIST_HEAD(&smb->smsi_hook_list);
+
INIT_LIST_HEAD(&smb->smsi_plg_list);
+ init_rwsem(&smb->plg_sem);
+
+ if (SMFS_IS(flags, SMFS_PLG_AUDIT))
+ smfs_init_audit(sb);
+ if (SMFS_IS(flags, SMFS_PLG_KML))
+ smfs_init_kml(sb);
+ if (SMFS_IS(flags, SMFS_PLG_LRU))
+ smfs_init_lru(sb);
+#if CONFIG_SNAPFS
+ if (SMFS_IS(flags, SMFS_PLG_COW))
+ smfs_init_cow(sb);
+#endif
RETURN(0);
}
-static void smfs_cleanup_hook_ops(struct smfs_super_info *smb)
+static void smfs_remove_plugins(struct super_block *sb)
{
- struct list_head *hlist = &smb->smsi_hook_list;
- ENTRY;
-
- while (!list_empty(hlist)) {
- struct smfs_hook_ops *smfs_hops;
+ struct smfs_plugin * plg, *tmp;
+ struct smfs_super_info *smb = S2SMI(sb);
+ struct list_head * plist = &smb->smsi_plg_list;
- smfs_hops = list_entry(hlist->next, struct smfs_hook_ops,
- smh_list);
- CERROR("Unregister %s hook ops\n", smfs_hops->smh_name);
-
- smfs_unregister_hook_ops(smb, smfs_hops->smh_name);
- smfs_free_hook_ops(smfs_hops);
- }
- EXIT;
-}
-static void smfs_cleanup_smb(struct super_block *sb)
-{
- struct smfs_super_info *smb;
ENTRY;
-
- smb = S2SMI(sb);
- if (smb)
- OBD_FREE(smb, sizeof(*smb));
- EXIT;
-}
-
-void smfs_cleanup_hooks(struct smfs_super_info *smb)
-{
- if (SMFS_CACHE_HOOK(smb))
- cache_space_hook_exit(smb);
- if (SMFS_DO_REC(smb))
- smfs_rec_cleanup(smb);
-#if CONFIG_SNAPFS
- if (SMFS_DO_COW(smb))
- smfs_cow_cleanup(smb);
-#endif
- smfs_cleanup_hook_ops(smb);
+ list_for_each_entry_safe(plg, tmp, plist, plg_list) {
+ plg->plg_exit(sb, plg->plg_private);
+ }
+
+ EXIT;
}
void smfs_put_super(struct super_block *sb)
{
- struct smfs_super_info *smfs_info = S2SMI(sb);
-
- smfs_cleanup_hooks(smfs_info);
-
- if (sb)
- smfs_umount_cache(smfs_info);
- smfs_cleanup_smb(sb);
-}
-
-static int smfs_init_hooks(struct super_block *sb)
-{
+ struct smfs_super_info *smb = S2SMI(sb);
ENTRY;
-
- if (SMFS_DO_REC(S2SMI(sb)))
- smfs_rec_init(sb);
- if (SMFS_CACHE_HOOK(S2SMI(sb)))
- cache_space_hook_init(sb);
-#if CONFIG_SNAPFS
- if (SMFS_DO_COW(S2SMI(sb)))
- smfs_cow_init(sb);
-#endif
- RETURN(0);
+ smfs_remove_plugins(sb);
+
+ dput(sb->s_root);
+
+ if (smb->smsi_mnt)
+ smfs_umount_cache(smb);
+
+ smfs_cleanup_smb(smb);
+ EXIT;
}
-extern char* smfs_options(char*, char**, char**, char*, int *);
-
int smfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct inode *root_inode = NULL;
+ struct inode *back_root_inode = NULL;
struct smfs_super_info *smb = NULL;
- char *devstr = NULL, *typestr = NULL;
- char *opts = NULL, *cache_data = NULL;
- unsigned long page;
- int err = 0;
- ino_t root_ino;
-
+ char *devstr = NULL, *typestr = NULL;
+ unsigned long page = 0;
+ char *opts = NULL;
+ int flags = 0;
+ int err = 0;
+
ENTRY;
+
+ if (!data) {
+ CERROR("no mount options. At least name and dev are needed\n");
+ err = -EINVAL;
+ goto out_err;
+ }
- CDEBUG(D_SUPER, "mount opts: %s\n", data ?
- (char *)data : "(none)");
+ CDEBUG(D_SUPER, "mount opts: %s\n", (char *)data);
smb = smfs_init_smb(sb);
if (!smb)
RETURN(-ENOMEM);
-
- page = __get_free_page(GFP_KERNEL);
- if (!page)
- GOTO(out_err, err = -ENOMEM);
- memset((void *)page, 0, PAGE_SIZE);
- opts = (char *)page;
+ lock_kernel();
- cache_data = smfs_options(data, &devstr, &typestr, opts,
- &smb->smsi_flags);
- if (*cache_data) {
- CWARN("smfs_fill_super(): options parsing stoped at "
- "option %s\n", cache_data);
+ /* 2.6.9 selinux wants a full option page for do_kern_mount (bug6471) */
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page) {
+ err = -ENOMEM;
+ goto out_err;
}
-
+ opts = (char *)page;
+
+ err = smfs_options(data, &devstr, &typestr, opts, &flags);
+ if (err)
+ goto out_err;
+
if (!typestr || !devstr) {
CERROR("mount options name and dev are mandatory\n");
- free_page(page);
- GOTO(out_err, err = -EINVAL);
+ err = -EINVAL;
+ goto out_err;
}
+ CDEBUG(D_SUPER, "backfs mount opts: %s\n", opts);
+
err = smfs_mount_cache(smb, devstr, typestr, opts);
- free_page(page);
-
if (err) {
CERROR("Can not mount %s as %s\n", devstr, typestr);
- GOTO(out_err, err);
+ goto out_err;
}
+ free_page(page);
+ page = 0;
+
duplicate_sb(sb, smb->smsi_sb);
sb->s_bdev = smb->smsi_sb->s_bdev;
sm_set_sb_ops(smb->smsi_sb, sb);
- err = smfs_init_hook_ops(smb);
- if (err) {
- CERROR("Can not init super hook ops err %d\n", err);
- smfs_umount_cache(smb);
- GOTO(out_err, err);
- }
-
/* init the root_inode of smfs. */
- //dget(S2CSB(sb)->s_root);
- root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
- root_inode = smfs_get_inode(sb, root_ino, NULL, 0);
+ back_root_inode = S2CSB(sb)->s_root->d_inode;
+ root_inode = smfs_get_inode(sb, back_root_inode, NULL, 0);
CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
- sb->s_op->read_inode, root_ino, root_inode);
+ sb->s_op->read_inode, root_inode->i_ino, root_inode);
sb->s_root = d_alloc_root(root_inode);
-
if (!sb->s_root) {
- smfs_umount_cache(smb);
- GOTO(out_err, err = -ENOMEM);
+ err = -ENOMEM;
+ goto out_err;
}
- err = smfs_init_hooks(sb);
- if (err) {
- smfs_umount_cache(smb);
- GOTO(out_err, err);
- }
+ /* all entries created until post_setup() should not be logged */
+ SMFS_CLEAR((I2SMI(root_inode))->smi_flags, SMFS_PLG_ALL);
+
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
(ulong)sb, (ulong)&sb->u.generic_sbp);
(ulong)sb, smb->smsi_sb, (ulong)&sb->s_fs_info);
#endif
+ smfs_init_plugins(sb, flags);
+ unlock_kernel();
+ RETURN (0);
out_err:
- cleanup_option();
- if (err)
- smfs_cleanup_smb(sb);
- return err;
-}
-
-struct smfs_hook_ops *smfs_alloc_hook_ops(char *name, smfs_hook_func pre_hook,
- smfs_hook_func post_hook)
-{
- struct smfs_hook_ops *smfs_hops = NULL;
-
- ENTRY;
- OBD_ALLOC(smfs_hops, sizeof(struct smfs_hook_ops));
-
- if (!smfs_hops)
- RETURN(NULL);
-
- OBD_ALLOC(smfs_hops->smh_name, strlen(name) + 1);
-
- if (!smfs_hops->smh_name) {
- OBD_FREE(smfs_hops, sizeof(struct smfs_hook_ops));
- RETURN(NULL);
- }
-
- memcpy(smfs_hops->smh_name, name, strlen(name));
-
- smfs_hops->smh_post_op = post_hook;
- smfs_hops->smh_pre_op = pre_hook;
-
- RETURN(smfs_hops);
-}
-
-void smfs_free_hook_ops(struct smfs_hook_ops *hops)
-{
- if (hops) {
- if (hops->smh_name){
- OBD_FREE(hops->smh_name, strlen(hops->smh_name) + 1);
- }
- OBD_FREE(hops, sizeof(struct smfs_hook_ops));
- }
-}
-
-int smfs_register_hook_ops(struct smfs_super_info *smb,
- struct smfs_hook_ops *smh_ops)
-{
- struct list_head *hlist = &smb->smsi_hook_list;
- struct list_head *p;
- ENTRY;
-
- list_for_each(p, hlist) {
- struct smfs_hook_ops *found;
- found = list_entry(p, struct smfs_hook_ops, smh_list);
- if (!strcmp(found->smh_name, smh_ops->smh_name)) {
- CWARN("hook ops %s list reregister\n", smh_ops->smh_name);
- RETURN(0);
- }
- }
- list_add(&smh_ops->smh_list, hlist);
- RETURN(0);
-}
-
-struct smfs_hook_ops *smfs_unregister_hook_ops(struct smfs_super_info *smb,
- char *name)
-{
- struct list_head *hlist = &smb->smsi_hook_list;
- struct list_head *p;
- ENTRY;
-
- list_for_each(p, hlist) {
- struct smfs_hook_ops *found;
+ if (smb->smsi_mnt)
+ smfs_umount_cache(smb);
- found = list_entry(p, typeof(*found), smh_list);
- if (!memcmp(found->smh_name, name, strlen(name))) {
- list_del(p);
- RETURN(found);
- }
- }
+ if (page)
+ free_page(page);
- RETURN(NULL);
+ smfs_cleanup_smb(smb);
+ unlock_kernel();
+ RETURN(err);
}
void *smfs_trans_start(struct inode *inode, int op, void *desc_private)
{
struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
- CDEBUG(D_INFO, "trans start %p\n", fsfilt->fs_start);
-
- SMFS_TRANS_OP(inode, op);
-
- /* There are some problem here. fs_start in fsfilt is used by lustre
- * the journal blocks of write rec are not counted in FIXME later */
if (fsfilt->fs_start)
- return fsfilt->fs_start(inode, op, desc_private, 0);
+ return fsfilt->fs_start(inode, op, NULL, 0);
return NULL;
}
{
struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
- if (!handle)
- return;
-
- CDEBUG(D_INFO, "trans commit %p\n", fsfilt->fs_commit);
-
- if (fsfilt->fs_commit)
+ if (handle && fsfilt->fs_commit)
fsfilt->fs_commit(inode->i_sb, inode, handle, force_sync);
}
-
-
-int smfs_register_plugin(struct super_block * sb, struct smfs_plugin * new_plugin)
+/* Plugin API */
+int smfs_register_plugin(struct super_block * sb,
+ struct smfs_plugin * plg)
{
- struct smfs_plugin * plg = NULL;
- struct list_head * plist = &S2SMI(sb)->smsi_plg_list;
+ struct smfs_plugin * tmp = NULL;
+ struct smfs_super_info * smb = S2SMI(sb);
+ struct list_head * plist = &smb->smsi_plg_list;
+ int rc = 0;
ENTRY;
- list_for_each_entry(plg, plist, plg_list) {
- if (plg->plg_type == new_plugin->plg_type) {
+ down_write(&smb->plg_sem);
+ list_for_each_entry(tmp, plist, plg_list) {
+ if (tmp->plg_type == plg->plg_type) {
CWARN("Plugin is already registered\n");
- RETURN(-EEXIST);
+ rc = -EEXIST;
+ goto exit;
}
}
-
- OBD_ALLOC(plg, sizeof(*plg));
- if (!plg) {
- CWARN("Cannot allocate memory for plugin\n");
- RETURN(-ENOMEM);
- }
-
- memcpy(plg, new_plugin, sizeof(*plg));
+
list_add_tail(&plg->plg_list, plist);
-
+exit:
+ up_write(&smb->plg_sem);
RETURN(0);
}
-void * smfs_deregister_plugin(struct super_block * sb, int type)
+struct smfs_plugin * smfs_deregister_plugin(struct super_block *sb, int type)
{
struct smfs_plugin * plg = NULL;
- struct list_head * plist = &S2SMI(sb)->smsi_plg_list;
- void * priv = NULL;
-
+ struct smfs_super_info *smb = S2SMI(sb);
+ struct list_head * plist = &smb->smsi_plg_list;
+
ENTRY;
+ down_write(&smb->plg_sem);
list_for_each_entry(plg, plist, plg_list) {
if (plg->plg_type == type) {
list_del(&plg->plg_list);
- priv = plg->plg_private;
- OBD_FREE(plg, sizeof(*plg));
break;
}
}
+ up_write(&smb->plg_sem);
+ RETURN(plg);
+}
+
+void smfs_pre_hook (struct inode * inode, hook_op op, void * msg)
+{
+ struct smfs_super_info *smb = S2SMI(inode->i_sb);
+ struct smfs_inode_info *smi = I2SMI(inode);
+ struct list_head *hlist = &smb->smsi_plg_list;
+ struct smfs_plugin *plg;
- RETURN(priv);
+ //ENTRY;
+ LASSERT(op < HOOK_MAX);
+ //call hook operations
+ down_read(&smb->plg_sem);
+ list_for_each_entry(plg, hlist, plg_list) {
+ //check that plugin is active
+ if(!SMFS_IS(smb->plg_flags, plg->plg_type))
+ continue;
+ //check that inode is allowed
+ if (!SMFS_IS(smi->smi_flags, plg->plg_type))
+ continue;
+
+ if (plg->plg_pre_op)
+ plg->plg_pre_op(op, inode, msg, 0, plg->plg_private);
+ }
+ up_read(&smb->plg_sem);
+ //EXIT;
+}
+
+void smfs_post_hook (struct inode * inode, hook_op op, void * msg, int ret)
+{
+ struct smfs_super_info *smb = S2SMI(inode->i_sb);
+ //struct smfs_inode_info *smi = I2SMI(inode);
+ struct list_head *hlist = &smb->smsi_plg_list;
+ struct smfs_plugin *plg;
+
+ //ENTRY;
+ down_read(&smb->plg_sem);
+ list_for_each_entry(plg, hlist, plg_list) {
+ //check that plugin is active
+ if(!SMFS_IS(smb->plg_flags, plg->plg_type))
+ continue;
+ /* this will be checked inside plg_post_op()
+ if (!SMFS_IS(smi->smi_flags, plg->plg_type))
+ continue;
+ */
+ if (plg->plg_post_op)
+ plg->plg_post_op(op, inode, msg, ret, plg->plg_private);
+ }
+ up_read(&smb->plg_sem);
+ //EXIT;
+}
+
+int smfs_helper (struct super_block * sb, int op, void * msg)
+{
+ struct smfs_super_info *smb = S2SMI(sb);
+ struct list_head *hlist = &smb->smsi_plg_list;
+ struct smfs_plugin *plg, *tmp;
+ int rc = 0;
+
+ //ENTRY;
+ LASSERT(op < PLG_HELPER_MAX);
+ //call hook operations
+ down_read(&smb->plg_sem);
+ list_for_each_entry_safe(plg, tmp, hlist, plg_list) {
+ //check that plugin is active
+ if(!SMFS_IS(smb->plg_flags, plg->plg_type) &&
+ !(op == PLG_START || op == PLG_EXIT))
+ continue;
+
+ if (plg->plg_helper)
+ rc += plg->plg_helper(op, sb, msg, plg->plg_private);
+ }
+ up_read(&smb->plg_sem);
+ //EXIT;
+
+ return rc;
}
+void * smfs_get_plg_priv(struct smfs_super_info * smb, int type)
+{
+ struct list_head *hlist = &smb->smsi_plg_list;
+ struct smfs_plugin *plg, *tmp;
+
+ list_for_each_entry_safe(plg, tmp, hlist, plg_list) {
+ if (plg->plg_type == type) {
+ return (plg->plg_private);
+ }
+ }
+
+ EXIT;
+
+ return NULL;
+}