MODULES := smfs
-smfs-objs := super.o options.o inode.o cache.o cache_space.o dir.o ioctl.o
-smfs-objs += sysctl.o file.o symlink.o smfs_lib.o kml.o smfs_llog.o
-smfs-objs += mds_kml.o ost_kml.o
+smfs-objs := super.o inode.o cache.o dir.o fsfilt.o ioctl.o
+smfs-objs += sysctl.o file.o symlink.o smfs_lib.o smfs_llog.o
+smfs-objs += kml.o mds_kml.o ost_kml.o cache_space.o
@SNAPFS_TRUE@smfs-objs += smfs_cow.o
@INCLUDE_RULES@
static struct cache_purge_queue smfs_cpq;
static struct cache_purge_queue *cpq = &smfs_cpq;
-#define CACHE_HOOK "cache_hook"
-int cache_space_pre_hook(struct inode *inode, void *dentry,
- void *data1, void *data2, int op, void *handle)
-{
- int rc = 0;
- ENTRY;
-
- if (smfs_cache_hook(inode)) {
- if (!handle) {
- handle = smfs_trans_start(inode, KML_CACHE_NOOP, NULL);
- if (IS_ERR(handle)) {
- RETURN(PTR_ERR(handle));
- }
- }
- cache_space_pre(inode, op);
- }
- RETURN(rc);
-}
-
-int cache_space_post_hook(struct inode *inode, void *de, void *data1,
- void *data2, int op, void *handle)
-{
- int rc = 0;
- ENTRY;
- if (smfs_cache_hook(inode)) {
- struct inode *new_inode = (struct inode*)data1;
- struct dentry *new_dentry = (struct dentry*)data2;
- struct dentry *dentry = (struct dentry *)de;
-
- LASSERT(handle != NULL);
- rc = cache_space_post(op, handle, inode, dentry, new_inode,
- new_dentry);
- }
- RETURN(rc);
-}
-
-int cache_space_hook_init(struct super_block *sb)
-{
- struct smfs_super_info *smfs_info = S2SMI(sb);
- struct smfs_hook_ops *cache_hops;
- int rc = 0;
- ENTRY;
-
- cache_hops = smfs_alloc_hook_ops(CACHE_HOOK, cache_space_pre_hook,
- cache_space_post_hook);
- if (!cache_hops) {
- RETURN(-ENOMEM);
- }
- rc = smfs_register_hook_ops(smfs_info, cache_hops);
- if (rc) {
- smfs_free_hook_ops(cache_hops);
- RETURN(rc);
- }
- SMFS_SET_CACHE_HOOK(smfs_info);
-
- RETURN(0);
-}
-
-int cache_space_hook_exit(struct smfs_super_info *smfs_info)
-{
- struct smfs_hook_ops *cache_hops;
-
- cache_hops = smfs_unregister_hook_ops(smfs_info, CACHE_HOOK);
- smfs_free_hook_ops(cache_hops);
-
- SMFS_CLEAN_CACHE_HOOK(smfs_info);
- return 0;
-}
-
static int cache_leaf_node(struct dentry *dentry, __u64 *active_entry)
{
struct inode *inode = dentry->d_inode;
- if (!dentry->d_inode)
+ if (!inode)
return 0;
+
if (S_ISDIR(inode->i_mode)) {
if (inode->i_nlink != 2)
return 0;
EXIT;
}
-void cache_space_pre(struct inode *inode, int op)
-{
- ENTRY;
-
- /* FIXME have not used op */
- check_cache_space();
-
- EXIT;
-}
-
static int cache_space_hook_lru(struct inode *inode, struct inode *parent,
- void *handle, int op, int flags)
+ int op, int flags)
{
struct fsfilt_operations *fsops = S2SMI(cpq->cpq_sb)->sm_fsfilt;
struct llog_ctxt *ctxt = cpq->cpq_loghandle->lgh_ctxt;
struct llog_lru_rec *llr = NULL;
struct llog_cookie *logcookie = NULL;
+ void * handle = NULL;
int cookie_size = sizeof(struct llog_cookie);
int rc = 0, err;
ENTRY;
if (!logcookie)
GOTO(out, rc = -ENOMEM);
- if (op & CACHE_SPACE_DELETE) {
+ if (op & CACHE_SPACE_DELETE) {
rc = get_lru_logcookie(inode, logcookie);
if (rc < 0)
- GOTO(out, rc);
+ goto out;
if (logcookie->lgc_lgl.lgl_oid == 0) {
CWARN("inode %lu/%u is not in lru list\n",
inode->i_ino, inode->i_generation);
- GOTO(insert, rc = -ENOENT);
+ rc = -ENOENT;
}
- if (flags && llog_cat_half_bottom(logcookie, ctxt->loc_handle))
- GOTO(out, rc = 0);
-
- rc = llog_cancel(ctxt, 1, logcookie, 0, NULL);
- if (!rc) {
- memset(logcookie, 0, cookie_size);
- rc = set_lru_logcookie(inode, handle, logcookie);
+ else {
+ rc = 0;
+ if (flags && llog_cat_half_bottom(logcookie, ctxt->loc_handle))
+ goto out;
+
+ rc = llog_cancel(ctxt, 1, logcookie, 0, NULL);
+ if (!rc) {
+ memset(logcookie, 0, cookie_size);
+ rc = set_lru_logcookie(inode, handle, logcookie);
+ }
if (rc)
- GOTO(out, rc);
- } else {
- CERROR("failed at llog_cancel: %d\n", rc);
- GOTO(out, rc);
+ goto out;
}
}
-insert:
- if (op & CACHE_SPACE_INSERT) {
+ if (op & CACHE_SPACE_INSERT) {
LASSERT(parent != NULL);
OBD_ALLOC(llr, sizeof(*llr));
if (llr == NULL)
RETURN(0);
}
-int cache_space_hook_setup(struct super_block *sb)
-{
- struct llog_ctxt *ctxt;
- int rc;
- ENTRY;
-
- /* first to initialize the cache lru catalog on local fs */
- rc = llog_catalog_setup(&ctxt, CACHE_LRU_LOG,
- S2SMI(sb)->smsi_exp,
- S2SMI(sb)->smsi_ctxt,
- S2SMI(sb)->sm_fsfilt,
- S2SMI(sb)->smsi_logs_dir,
- S2SMI(sb)->smsi_objects_dir);
- if (rc) {
- CERROR("failed to initialize cache lru list catalog %d\n", rc);
- RETURN(rc);
- }
- cpq->cpq_sb = sb;
- cpq->cpq_loghandle = ctxt->loc_handle;
-
- /* start cache purge daemon, only one daemon now */
- init_waitqueue_head(&cpq->cpq_waitq);
- init_completion(&cpq->cpq_comp);
- cpq->cpq_flags = 0;
-
- rc = kernel_thread(cache_purge_thread, NULL, CLONE_VM | CLONE_FILES);
- if (rc < 0) {
- CERROR("cannot start thread: %d\n", rc);
- GOTO(err_out, rc);
- }
- wait_for_completion(&cpq->cpq_comp);
-
- RETURN(0);
-err_out:
- llog_catalog_cleanup(ctxt);
- OBD_FREE(ctxt, sizeof(*ctxt));
- RETURN(rc);
-}
-
-int cache_space_hook_cleanup(void)
-{
- struct llog_ctxt *ctxt;
- int rc;
- ENTRY;
-
- init_completion(&cpq->cpq_comp);
- cpq->cpq_flags = SVC_STOPPING;
- wake_up(&cpq->cpq_waitq);
- wait_for_completion(&cpq->cpq_comp);
-
- ctxt = cpq->cpq_loghandle->lgh_ctxt;
- rc = llog_catalog_cleanup(ctxt);
- OBD_FREE(ctxt, sizeof(*ctxt));
-
- if (rc)
- CERROR("failed to clean up cache lru list catalog %d\n", rc);
-
- RETURN(rc);
-}
-
-static int cache_space_hook_create(void *handle, struct inode *dir,
- struct dentry *dentry, struct inode *new_dir,
- struct dentry *new_dentry)
+/* Hooks */
+static int cache_space_hook_create (struct inode *dir, struct dentry * dentry)
{
__u64 active_entry = 0;
int rc;
ENTRY;
LASSERT(cache_leaf_node(dentry, NULL));
- rc = cache_space_hook_lru(dentry->d_inode, dir, handle,
- CACHE_SPACE_INSERT, 0);
+ rc = cache_space_hook_lru(dentry->d_inode, dir, CACHE_SPACE_INSERT, 0);
if (rc)
RETURN(rc);
if (cache_leaf_node(dentry->d_parent, &active_entry)) {
- rc = cache_space_hook_lru(dir,NULL,handle,CACHE_SPACE_DELETE,0);
+ rc = cache_space_hook_lru(dir, NULL, CACHE_SPACE_DELETE, 0);
if (rc)
RETURN(rc);
}
rc = get_active_entry(dir, &active_entry);
active_entry ++;
if (!rc)
- rc = set_active_entry(dir, &active_entry, handle);
+ rc = set_active_entry(dir, &active_entry, NULL);
RETURN(rc);
}
-static int cache_space_hook_lookup(void *handle, struct inode *dir,
- struct dentry *dentry, struct inode *new_dir,
- struct dentry *new_dentry)
+static int cache_space_hook_lookup(struct inode *dir, struct dentry *dentry)
{
__u64 active_entry;
int rc = 0;
ENTRY;
if (cache_leaf_node(dentry, &active_entry))
- rc = cache_space_hook_lru(dentry->d_inode, dir, handle,
- CACHE_SPACE_DELETE | CACHE_SPACE_INSERT,1);
+ rc = cache_space_hook_lru(dentry->d_inode, dir,
+ CACHE_SPACE_DELETE | CACHE_SPACE_INSERT, 1);
RETURN(rc);
}
-static int cache_space_hook_link(void *handle, struct inode *dir,
- struct dentry *dentry, struct inode *new_dir,
- struct dentry *new_dentry)
+static int cache_space_hook_link(struct inode *dir, struct dentry *dentry)
{
__u64 active_entry = 0;
int rc = 0;
ENTRY;
if (cache_pre_leaf_node(dentry, NULL, 1)) {
- rc = cache_space_hook_lru(dentry->d_inode, NULL,
- handle, CACHE_SPACE_DELETE, 0);
+ rc = cache_space_hook_lru(dentry->d_inode, NULL,
+ CACHE_SPACE_DELETE, 0);
if (rc)
RETURN(rc);
}
if (cache_leaf_node(dentry->d_parent, &active_entry)) {
- rc = cache_space_hook_lru(dir, NULL, handle, CACHE_SPACE_DELETE, 0);
+ rc = cache_space_hook_lru(dir, NULL, CACHE_SPACE_DELETE, 0);
if (rc)
RETURN(rc);
}
rc = get_active_entry(dir, &active_entry);
active_entry ++;
if (!rc)
- rc = set_active_entry(dir, &active_entry, handle);
+ rc = set_active_entry(dir, &active_entry, NULL);
RETURN(rc);
}
-static int cache_space_hook_unlink(void *handle, struct inode *dir,
- struct dentry *dentry, struct inode *new_dir,
- struct dentry *new_dentry)
+static int cache_space_hook_unlink(struct inode *dir, struct dentry *dentry)
{
__u64 active_entry;
int rc = 0;
if (cache_pre_leaf_node(dentry, NULL, 0))
rc = cache_space_hook_lru(dentry->d_inode, NULL,
- handle, CACHE_SPACE_DELETE, 0);
+ CACHE_SPACE_DELETE, 0);
else if (cache_leaf_node(dentry, NULL))
rc = cache_space_hook_lru(dentry->d_inode, dir,
- handle, CACHE_SPACE_INSERT,0);
+ CACHE_SPACE_INSERT,0);
if (rc)
RETURN(rc);
rc = get_active_entry(dir, &active_entry);
active_entry --;
if (!rc)
- rc = set_active_entry(dir, &active_entry, handle);
+ rc = set_active_entry(dir, &active_entry, NULL);
if (!rc && cache_leaf_node(dentry->d_parent, &active_entry))
rc = cache_space_hook_lru(dir,
dentry->d_parent->d_parent->d_inode,
- handle, CACHE_SPACE_INSERT, 0);
+ CACHE_SPACE_INSERT, 0);
RETURN(rc);
}
-static int cache_space_hook_mkdir(void *handle, struct inode *dir,
- struct dentry *dentry, struct inode *new_dir,
- struct dentry *new_dentry)
+static int cache_space_hook_mkdir(struct inode *dir, struct dentry *dentry)
{
__u64 active_entry;
int rc;
ENTRY;
LASSERT(cache_leaf_node(dentry, &active_entry));
- rc = cache_space_hook_lru(dentry->d_inode, dir, handle,
- CACHE_SPACE_INSERT, 0);
+ rc = cache_space_hook_lru(dentry->d_inode, dir, CACHE_SPACE_INSERT, 0);
if (!rc && cache_pre_leaf_node(dentry->d_parent, &active_entry, 3))
- rc = cache_space_hook_lru(dir, NULL, handle, CACHE_SPACE_DELETE, 0);
+ rc = cache_space_hook_lru(dir, NULL, CACHE_SPACE_DELETE, 0);
RETURN(rc);
}
-static int cache_space_hook_rmdir(void *handle, struct inode *dir,
- struct dentry *dentry, struct inode *new_dir,
- struct dentry *new_dentry)
+static int cache_space_hook_rmdir(struct inode *dir, struct dentry *dentry)
{
__u64 active_entry;
int rc;
ENTRY;
LASSERT(cache_pre_leaf_node(dentry, &active_entry, 2));
- rc = cache_space_hook_lru(dentry->d_inode, NULL, handle,
+ rc = cache_space_hook_lru(dentry->d_inode, NULL,
CACHE_SPACE_DELETE, 0);
if (!rc && cache_leaf_node(dentry->d_parent, &active_entry))
rc = cache_space_hook_lru(dir,
dentry->d_parent->d_parent->d_inode,
- handle, CACHE_SPACE_INSERT, 0);
+ CACHE_SPACE_INSERT, 0);
RETURN(rc);
}
-static int cache_space_hook_rename(void *handle, struct inode *old_dir,
- struct dentry *old_dentry, struct inode *new_dir,
- struct dentry *new_dentry)
+static int cache_space_hook_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
__u64 active_entry;
int rc = 0;
if (new_dentry->d_inode) {
if (cache_pre_leaf_node(new_dentry, NULL, 0))
rc = cache_space_hook_lru(new_dentry->d_inode, NULL,
- handle, CACHE_SPACE_DELETE,0);
+ CACHE_SPACE_DELETE,0);
else if (cache_leaf_node(new_dentry, NULL))
rc = cache_space_hook_lru(new_dentry->d_inode,
- new_dir, handle,
+ new_dir,
CACHE_SPACE_INSERT,0);
}
if (!S_ISDIR(old_dentry->d_inode->i_mode)) {
if (cache_leaf_node(new_dentry->d_parent, &active_entry)) {
- rc = cache_space_hook_lru(new_dir, NULL, handle,
+ rc = cache_space_hook_lru(new_dir, NULL,
CACHE_SPACE_DELETE, 0);
if (rc)
RETURN(rc);
rc = get_active_entry(new_dir, &active_entry);
active_entry ++;
if (!rc)
- rc = set_active_entry(new_dir, &active_entry, handle);
+ rc = set_active_entry(new_dir, &active_entry, NULL);
if (rc)
RETURN(rc);
rc = get_active_entry(old_dir, &active_entry);
active_entry --;
if (!rc)
- rc = set_active_entry(old_dir, &active_entry, handle);
+ rc = set_active_entry(old_dir, &active_entry, NULL);
} else if (cache_pre_leaf_node(new_dentry->d_parent, &active_entry, 3)) {
- rc = cache_space_hook_lru(new_dir, NULL, handle,
+ rc = cache_space_hook_lru(new_dir, NULL,
CACHE_SPACE_DELETE, 0);
}
if (!rc && cache_leaf_node(old_dentry->d_parent, &active_entry)) {
rc = cache_space_hook_lru(old_dir,
old_dentry->d_parent->d_parent->d_inode,
- handle, CACHE_SPACE_INSERT, 0);
+ CACHE_SPACE_INSERT, 0);
}
RETURN(rc);
}
-typedef int (*cache_hook_op)(void *handle, struct inode *old_dir,
- struct dentry *old_dentry, struct inode *new_dir,
- struct dentry *new_dentry);
-
-static cache_hook_op cache_space_hook_ops[HOOK_MAX + 1] = {
- [HOOK_CREATE] cache_space_hook_create,
- [HOOK_LOOKUP] cache_space_hook_lookup,
- [HOOK_LINK] cache_space_hook_link,
- [HOOK_UNLINK] cache_space_hook_unlink,
- [HOOK_SYMLINK] cache_space_hook_create,
- [HOOK_MKDIR] cache_space_hook_mkdir,
- [HOOK_RMDIR] cache_space_hook_rmdir,
- [HOOK_MKNOD] cache_space_hook_create,
- [HOOK_RENAME] cache_space_hook_rename,
+static int lru_create (struct inode * inode, void * arg)
+{
+ struct hook_msg * msg = arg;
+ return cache_space_hook_create(inode, msg->dentry);
+}
+static int lru_lookup (struct inode * inode, void * arg)
+{
+ struct hook_msg * msg = arg;
+ return cache_space_hook_lookup(inode, msg->dentry);
+}
+static int lru_link (struct inode * inode, void * arg)
+{
+ struct hook_link_msg * msg = arg;
+ return cache_space_hook_link(inode, msg->dentry);
+}
+static int lru_unlink (struct inode * inode, void * arg)
+{
+ struct hook_unlink_msg * msg = arg;
+ return cache_space_hook_unlink(inode, msg->dentry);
+}
+static int lru_symlink (struct inode * inode, void * arg)
+{
+ struct hook_symlink_msg * msg = arg;
+ return cache_space_hook_create(inode, msg->dentry);
+}
+static int lru_mkdir (struct inode * inode, void * arg)
+{
+ struct hook_msg * msg = arg;
+ return cache_space_hook_mkdir(inode, msg->dentry);
+}
+static int lru_rmdir (struct inode * inode, void * arg)
+{
+ struct hook_unlink_msg * msg = arg;
+ return cache_space_hook_rmdir(inode, msg->dentry);
+}
+static int lru_rename (struct inode * inode, void * arg)
+{
+ struct hook_rename_msg * msg = arg;
+ return cache_space_hook_rename(inode, msg->dentry,
+ msg->new_dir, msg->new_dentry);
+}
+
+
+typedef int (*post_lru_op)(struct inode *inode, void * msg);
+static post_lru_op smfs_lru_post[HOOK_MAX] = {
+ [HOOK_CREATE] lru_create,
+ [HOOK_LOOKUP] lru_lookup,
+ [HOOK_LINK] lru_link,
+ [HOOK_UNLINK] lru_unlink,
+ [HOOK_SYMLINK] lru_symlink,
+ [HOOK_MKDIR] lru_mkdir,
+ [HOOK_RMDIR] lru_rmdir,
+ [HOOK_MKNOD] lru_create,
+ [HOOK_RENAME] lru_rename,
[HOOK_SETATTR] NULL,
[HOOK_WRITE] NULL,
[HOOK_READDIR] NULL,
};
-int cache_space_post(int op, void *handle, struct inode *old_dir,
- struct dentry *old_dentry, struct inode *new_dir,
- struct dentry *new_dentry)
+static int smfs_lru_pre_op(int op, struct inode *inode, void * msg, int ret,
+ void *priv)
+{
+ int rc = 0;
+ ENTRY;
+
+ /* FIXME have not used op */
+ check_cache_space();
+
+ RETURN(rc);
+}
+
+static int smfs_lru_post_op(int op, struct inode *inode, void *msg, int ret,
+ void *priv)
+{
+ int rc = 0;
+
+ ENTRY;
+ if (ret)
+ RETURN(0);
+
+ if (smfs_lru_post[op])
+ rc = smfs_lru_post[op](inode, msg);
+
+ RETURN(rc);
+}
+
+/* Helpers */
+static int smfs_exit_lru(struct super_block *sb, void * arg, void * priv)
+{
+ ENTRY;
+
+ smfs_deregister_plugin(sb, SMFS_PLG_LRU);
+
+ EXIT;
+ return 0;
+}
+
+static int smfs_trans_lru (struct super_block *sb, void *arg, void * priv)
+{
+ int size;
+
+ ENTRY;
+
+ size = 20;//LDISKFS_INDEX_EXTRA_TRANS_BLOCKS+LDISKFS_DATA_TRANS_BLOCKS;
+
+ RETURN(size);
+}
+
+static int smfs_start_lru(struct super_block *sb, void *arg, void * priv)
{
int rc = 0;
+ struct smfs_super_info * smb = S2SMI(sb);
+ struct llog_ctxt *ctxt;
+
ENTRY;
+
+ if (SMFS_IS(smb->plg_flags, SMFS_PLG_LRU))
+ RETURN(0);
- LASSERT(op <= HOOK_MAX + 1);
+ /* first to initialize the cache lru catalog on local fs */
+ rc = llog_catalog_setup(&ctxt, CACHE_LRU_LOG, smb->smsi_exp,
+ smb->smsi_ctxt, smb->sm_fsfilt,
+ smb->smsi_logs_dir,
+ smb->smsi_objects_dir);
+ if (rc) {
+ CERROR("failed to initialize cache lru list catalog %d\n", rc);
+ RETURN(rc);
+ }
+ cpq->cpq_sb = sb;
+ cpq->cpq_loghandle = ctxt->loc_handle;
- if (cache_space_hook_ops[op])
- rc = cache_space_hook_ops[op](handle, old_dir, old_dentry,
- new_dir, new_dentry);
+ /* start cache purge daemon, only one daemon now */
+ init_waitqueue_head(&cpq->cpq_waitq);
+ init_completion(&cpq->cpq_comp);
+ cpq->cpq_flags = 0;
+
+ rc = kernel_thread(cache_purge_thread, NULL, CLONE_VM | CLONE_FILES);
+ if (rc < 0) {
+ CERROR("cannot start thread: %d\n", rc);
+ goto err_out;
+ }
+ wait_for_completion(&cpq->cpq_comp);
+
+ SMFS_SET(smb->plg_flags, SMFS_PLG_LRU);
+
+ RETURN(0);
+err_out:
+ llog_catalog_cleanup(ctxt);
+ OBD_FREE(ctxt, sizeof(*ctxt));
RETURN(rc);
}
+
+static int smfs_stop_lru(struct super_block *sb, void *arg, void * priv)
+{
+ struct smfs_super_info * smb = S2SMI(sb);
+ struct llog_ctxt *ctxt;
+ int rc;
+ ENTRY;
+
+ if (!SMFS_IS(smb->plg_flags, SMFS_PLG_LRU))
+ RETURN(0);
+
+ SMFS_CLEAR(smb->plg_flags, SMFS_PLG_LRU);
+
+ init_completion(&cpq->cpq_comp);
+ cpq->cpq_flags = SVC_STOPPING;
+ wake_up(&cpq->cpq_waitq);
+ wait_for_completion(&cpq->cpq_comp);
+
+ ctxt = cpq->cpq_loghandle->lgh_ctxt;
+ rc = llog_catalog_cleanup(ctxt);
+ OBD_FREE(ctxt, sizeof(*ctxt));
+ RETURN(0);
+}
+
+typedef int (*lru_helper)(struct super_block * sb, void *msg, void *);
+static lru_helper smfs_lru_helpers[PLG_HELPER_MAX] = {
+ [PLG_EXIT] smfs_exit_lru,
+ [PLG_START] smfs_start_lru,
+ [PLG_STOP] smfs_stop_lru,
+ [PLG_TRANS_SIZE] smfs_trans_lru,
+ [PLG_TEST_INODE] NULL,
+ [PLG_SET_INODE] NULL,
+};
+
+static int smfs_lru_help_op(int code, struct super_block * sb,
+ void * arg, void * priv)
+{
+ ENTRY;
+ if (smfs_lru_helpers[code])
+ smfs_lru_helpers[code](sb, arg, priv);
+ RETURN(0);
+}
+
+int smfs_init_lru(struct super_block *sb)
+{
+ struct smfs_plugin plg = {
+ .plg_type = SMFS_PLG_LRU,
+ .plg_pre_op = &smfs_lru_pre_op,
+ .plg_post_op = &smfs_lru_post_op,
+ .plg_helper = &smfs_lru_help_op,
+ .plg_private = NULL
+ };
+ int rc = 0;
+
+ ENTRY;
+
+ rc = smfs_register_plugin(sb, &plg);
+
+ RETURN(rc);
+}
+
+
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * lustre/smfs/journal.c
- * Lustre filesystem abstraction routines
- *
- * Copyright (C) 2004 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/obd_class.h>
-#include <linux/obd_support.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_idl.h>
-#include <linux/lustre_fsfilt.h>
-#include <linux/lustre_smfs.h>
-#include <linux/lvfs.h>
-#include "smfs_internal.h"
-
-#define KML_BUF_REC_INIT(buffer, pbuf, len) \
-do { \
- pbuf = buffer + sizeof(int); \
- len -= sizeof(int); \
-} while (0)
-
-#define KML_BUF_REC_END(buffer, length, pbuf) \
-do { \
- int len = length; \
- memcpy(buffer, &len, sizeof(len)); \
- length += sizeof(int); \
- pbuf = buffer + length; \
-} while (0)
-
-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 NULL;
-}
-
-void smfs_trans_commit(struct inode *inode, void *handle, int force_sync)
-{
- 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)
- fsfilt->fs_commit(inode->i_sb, inode, handle, force_sync);
-}
-
-/*smfs_path is gotten from intermezzo*/
-static char* smfs_path(struct dentry *dentry, struct dentry *root, char *buffer,
- int buflen)
-{
- char * end = buffer + buflen;
- char * name = buffer;
- char * buf_end = buffer + buflen;
- char * retval;
-
- *--end = '\0';
- buflen--;
- /* Get '/' right */
- retval = end-1;
- *retval = '/';
-
- for (;;) {
- struct dentry * parent;
- int namelen;
-
- if (dentry == root)
- break;
- parent = dentry->d_parent;
- if (dentry == parent)
- break;
- namelen = dentry->d_name.len;
- buflen -= namelen + 1;
- if (buflen < 0)
- break;
- end -= namelen;
- memcpy(end, dentry->d_name.name, namelen);
- *--end = '/';
- retval = end;
- dentry = parent;
- }
-
- while (end != buf_end)
- *name++ = *end++;
- *name = '\0';
- return retval;
-}
-
-static int smfs_log_path(struct super_block *sb,
- struct dentry *dentry,
- char *buffer,
- int buffer_len)
-{
- struct dentry *root=sb->s_root;
- char *p_name = buffer + sizeof(int);
- char *name = NULL;
- int namelen = 0;
- if (dentry) {
- name = smfs_path(dentry, root, p_name, buffer_len - sizeof(int));
- namelen = cpu_to_le32(strlen(p_name));
- memcpy(buffer, &namelen, sizeof(int));
- }
- namelen += sizeof(int);
- RETURN(namelen);
-}
-
-static inline int log_it(char *buffer, void *data, int length)
-{
- memcpy(buffer, &length, sizeof(int));
- memcpy(buffer + sizeof(int), data, length);
- return (sizeof(int) + length);
-}
-
-static int smfs_pack_rec (char *buffer, struct dentry *dentry,
- struct inode *dir, void *data1,
- void *data2, int op)
-{
- smfs_pack_rec_func pack_func;
- int rc;
-
- pack_func = smfs_get_rec_pack_type(dir->i_sb);
- if (!pack_func) {
- return (0);
- }
- rc = pack_func(buffer, dentry, dir, data1, data2, op);
- return rc;
-}
-
-int smfs_post_rec_create(struct inode *dir, struct dentry *dentry,
- void *data1, void *data2)
-{
- struct smfs_super_info *sinfo;
- char *buffer = NULL, *pbuf;
- int rc = 0, length = 0, buf_len = 0;
-
- sinfo = S2SMI(dentry->d_inode->i_sb);
- if (!sinfo)
- RETURN(-EINVAL);
-
- OBD_ALLOC(buffer, PAGE_SIZE);
- if (!buffer)
- GOTO(exit, rc = -ENOMEM);
-
- buf_len = PAGE_SIZE;
- KML_BUF_REC_INIT(buffer, pbuf, buf_len);
- rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
- if (rc < 0)
- GOTO(exit, rc);
- length = rc;
- KML_BUF_REC_END(buffer, length, pbuf);
-
- rc = smfs_pack_rec(pbuf, dentry, dir,
- data1, data2, REINT_CREATE);
- if (rc <= 0)
- GOTO(exit, rc);
- else
- length += rc;
- rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
-exit:
- if (buffer)
- OBD_FREE(buffer, PAGE_SIZE);
-
- RETURN(rc);
-}
-
-static int smfs_post_rec_link(struct inode *dir,
- struct dentry *dentry,
- void *data1,
- void *data2)
-{
- struct smfs_super_info *sinfo;
- struct dentry *old_dentry = (struct dentry *)data1;
- char *buffer = NULL, *pbuf = NULL;
- int rc = 0, length = 0, buf_len = 0;
-
- sinfo = S2SMI(dir->i_sb);
- if (!sinfo)
- RETURN(-EINVAL);
- OBD_ALLOC(buffer, PAGE_SIZE);
- if (!buffer)
- GOTO(exit, rc = -ENOMEM);
-
- buf_len = PAGE_SIZE;
- KML_BUF_REC_INIT(buffer, pbuf, buf_len);
- rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
- if (rc < 0)
- GOTO(exit, rc);
-
- length = rc;
- KML_BUF_REC_END(buffer, length, pbuf);
-
- rc = smfs_pack_rec(pbuf, dentry, dir, dentry->d_parent,
- old_dentry->d_parent, REINT_LINK);
- if (rc <= 0)
- GOTO(exit, rc);
- else
- length += rc;
- rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
-exit:
- if (buffer)
- OBD_FREE(buffer, PAGE_SIZE);
-
- RETURN(rc);
-}
-
-static int smfs_post_rec_unlink(struct inode *dir, struct dentry *dentry,
- void *data1, void *data2)
-{
- struct smfs_super_info *sinfo;
- int mode = *((int*)data1);
- char *buffer = NULL, *pbuf = NULL;
- int length = 0, rc = 0, buf_len = 0;
-
- sinfo = S2SMI(dentry->d_inode->i_sb);
- if (!sinfo)
- RETURN(-EINVAL);
-
- OBD_ALLOC(buffer, PAGE_SIZE);
- if (!buffer)
- GOTO(exit, rc = -ENOMEM);
-
- buf_len = PAGE_SIZE;
- KML_BUF_REC_INIT(buffer, pbuf, buf_len);
- rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
- if (rc < 0)
- GOTO(exit, rc);
-
- length = rc;
- KML_BUF_REC_END(buffer, length, pbuf);
- rc = smfs_pack_rec(pbuf, dentry, dir,
- &mode, NULL, REINT_UNLINK);
- if (rc <= 0)
- GOTO(exit, rc);
- else
- length += rc;
-
- rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
-exit:
- if (buffer)
- OBD_FREE(buffer, PAGE_SIZE);
-
- RETURN(rc);
-}
-
-static int smfs_post_rec_rename(struct inode *dir,
- struct dentry *dentry,
- void *data1,
- void *data2)
-{
- struct smfs_super_info *sinfo;
- struct inode *new_dir = (struct inode *)data1;
- struct dentry *new_dentry = (struct dentry *)data2;
- char *buffer = NULL, *pbuf = NULL;
- int rc = 0, length = 0, buf_len = 0;
-
- sinfo = S2SMI(dir->i_sb);
- if (!sinfo)
- RETURN(-EINVAL);
-
- OBD_ALLOC(buffer, PAGE_SIZE);
- if (!buffer)
- GOTO(exit, rc = -ENOMEM);
-
- buf_len = PAGE_SIZE;
- KML_BUF_REC_INIT(buffer, pbuf, buf_len);
- rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
- if (rc < 0)
- GOTO(exit, rc);
-
- pbuf += rc;
- length += rc;
- buf_len -= rc;
- /*record new_dentry path*/
- rc = smfs_log_path(dir->i_sb, new_dentry, pbuf, buf_len);
- if (rc < 0)
- GOTO(exit, rc);
-
- length += rc;
- KML_BUF_REC_END(buffer, length, pbuf);
-
- rc = smfs_pack_rec(pbuf, dentry, dir,
- new_dir, new_dentry, REINT_RENAME);
- if (rc <= 0)
- GOTO(exit, rc);
- length += rc;
-
- rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
-exit:
- if (buffer)
- OBD_FREE(buffer, PAGE_SIZE);
- RETURN(rc);
-}
-
-static int smfs_insert_extents_ea(struct inode *inode, size_t from, loff_t num)
-{
- struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
- int rc = 0;
-
- if (SMFS_INODE_OVER_WRITE(inode))
- RETURN(rc);
-
- rc = fsfilt->fs_insert_extents_ea(inode, OFF2BLKS(from, inode),
- SIZE2BLKS(num, inode));
- RETURN(rc);
-}
-
-static int smfs_remove_extents_ea(struct inode *inode, size_t from, loff_t num)
-{
- struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
- int rc = 0;
-
- rc = fsfilt->fs_remove_extents_ea(inode, OFF2BLKS(from, inode),
- SIZE2BLKS(num, inode));
-
- RETURN(rc);
-}
-
-static int smfs_remove_all_extents_ea(struct inode *inode)
-{
- struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
- int rc = 0;
-
- rc = fsfilt->fs_remove_extents_ea(inode, 0, 0xffffffff);
- RETURN(rc);
-}
-static int smfs_init_extents_ea(struct inode *inode)
-{
- struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
- int rc = 0;
-
- rc = fsfilt->fs_init_extents_ea(inode);
-
- RETURN(rc);
-}
-static int smfs_set_dirty_flags(struct inode *inode, int flags)
-{
- struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
- void *handle;
- int rc = 0;
-
- if (SMFS_INODE_OVER_WRITE(inode))
- RETURN(rc);
- /*FIXME later, the blocks needed in journal here will be recalculated*/
- handle = smfs_trans_start(inode, FSFILT_OP_SETATTR, NULL);
- if (IS_ERR(handle)) {
- CERROR("smfs_set_dirty_flag:no space for transaction\n");
- RETURN(-ENOSPC);
- }
- if ((!SMFS_INODE_DIRTY_WRITE(inode) && (!SMFS_INODE_OVER_WRITE(inode))) ||
- ((flags == SMFS_OVER_WRITE) && (SMFS_INODE_DIRTY_WRITE(inode)))) {
- rc = fsfilt->fs_set_xattr(inode, handle, REINT_EXTENTS_FLAGS,
- &flags, sizeof(int));
- if (rc)
- GOTO(out, rc);
- }
- if (flags == SMFS_OVER_WRITE)
- SMFS_SET_INODE_OVER_WRITE(inode);
- else
- SMFS_SET_INODE_DIRTY_WRITE(inode);
-out:
- smfs_trans_commit(inode, handle, 0);
- RETURN(rc);
-}
-
-int smfs_post_rec_setattr(struct inode *inode, struct dentry *dentry,
- void *data1, void *data2)
-{
- struct smfs_super_info *sinfo;
- struct iattr *attr = (struct iattr *)data1;
- char *buffer = NULL, *pbuf;
- int rc = 0, length = 0, buf_len = 0;
-
- sinfo = S2SMI(inode->i_sb);
- if (!sinfo)
- RETURN(-EINVAL);
-
- OBD_ALLOC(buffer, PAGE_SIZE);
- if (!buffer)
- GOTO(exit, rc = -ENOMEM);
-
- buf_len = PAGE_SIZE;
- KML_BUF_REC_INIT(buffer, pbuf, buf_len);
- rc = smfs_log_path(inode->i_sb, dentry, pbuf, buf_len);
- if (rc < 0)
- GOTO(exit, rc);
-
- length = rc;
- KML_BUF_REC_END(buffer, length, pbuf);
-
- rc = smfs_pack_rec(pbuf, dentry, inode,
- data1, data2, REINT_SETATTR);
- if (rc <= 0)
- GOTO(exit, rc);
- else
- length += rc;
-
- rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
- if (!rc) {
- if (attr && attr->ia_valid & ATTR_SIZE) {
- smfs_remove_extents_ea(inode, attr->ia_size,
- 0xffffffff);
- if (attr->ia_size == 0)
- smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
- else
- smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
- }
- }
-exit:
- if (buffer)
- OBD_FREE(buffer, PAGE_SIZE);
- RETURN(rc);
-}
-
-static int all_blocks_present_ea(struct inode *inode)
-{
- int rc = 0;
-
- RETURN(rc);
-}
-int smfs_post_rec_write(struct inode *dir, struct dentry *dentry,
- void *data1, void *data2)
-{
- struct smfs_super_info *sinfo;
- char *buffer = NULL, *pbuf;
- int rc = 0, length = 0, buf_len = 0;
-
- if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) &&
- !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) {
- sinfo = S2SMI(dentry->d_inode->i_sb);
- if (!sinfo)
- RETURN(-EINVAL);
-
- OBD_ALLOC(buffer, PAGE_SIZE);
- if (!buffer)
- GOTO(exit, rc = -ENOMEM);
-
- buf_len = PAGE_SIZE;
- KML_BUF_REC_INIT(buffer, pbuf, buf_len);
- rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
-
- if (rc < 0)
- GOTO(exit, rc);
- pbuf += rc;
- memcpy(buffer, &rc, sizeof(int));
- length = rc + sizeof(int);
-
- rc = smfs_pack_rec(pbuf, dentry, dir,
- data1, data2, REINT_WRITE);
- if (rc <= 0)
- GOTO(exit, rc);
- else
- length += rc;
-
- rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
- if (rc)
- GOTO(exit, rc);
- rc = smfs_init_extents_ea(dentry->d_inode);
- if (rc)
- GOTO(exit, rc);
- }
- if (dentry->d_inode->i_size == 0) {
- smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
- } else {
- /*insert extent EA*/
- loff_t off = *((loff_t*)data1);
- size_t count = *((size_t*)data2);
-
- rc = smfs_insert_extents_ea(dentry->d_inode, off, count);
- if (rc < 0)
- GOTO(exit, rc);
- if (all_blocks_present_ea(dentry->d_inode)){
- smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
- smfs_remove_all_extents_ea(dentry->d_inode);
- } else {
- smfs_set_dirty_flags(dentry->d_inode, SMFS_DIRTY_WRITE);
- }
- }
-exit:
- if (buffer)
- OBD_FREE(buffer, PAGE_SIZE);
- RETURN(rc);
-}
-
-typedef int (*post_kml_rec)(struct inode *dir, struct dentry *dentry,
- void *data1, void *data2);
-
-static post_kml_rec smfs_kml_post[HOOK_MAX + 1] = {
- [HOOK_CREATE] smfs_post_rec_create,
- [HOOK_LOOKUP] NULL,
- [HOOK_LINK] smfs_post_rec_link,
- [HOOK_UNLINK] smfs_post_rec_unlink,
- [HOOK_SYMLINK] smfs_post_rec_create,
- [HOOK_MKDIR] smfs_post_rec_create,
- [HOOK_RMDIR] smfs_post_rec_unlink,
- [HOOK_MKNOD] smfs_post_rec_create,
- [HOOK_RENAME] smfs_post_rec_rename,
- [HOOK_SETATTR] smfs_post_rec_setattr,
- [HOOK_WRITE] smfs_post_rec_write,
-};
-
-int smfs_post_kml_rec(struct inode *dir, struct dentry *dst_dentry,
- void *data1, void *data2, int op)
-{
- if (smfs_kml_post[op]) {
- return smfs_kml_post[op](dir, dst_dentry, data1, data2);
- }
- return 0;
-}
pbuf = buffer + length; \
} while (0)
-static smfs_pack_rec_func smfs_get_rec_pack_type(struct super_block *sb)
+
+static int smfs_llog_process_rec_cb(struct llog_handle *handle,
+ struct llog_rec_hdr *rec, void *data)
{
- int idx = 0;
- struct smfs_super_info *smsi = S2SMI(sb);
+ char *rec_buf ;
+ struct smfs_proc_args *args = (struct smfs_proc_args *)data;
+ struct lvfs_run_ctxt saved;
+ int rc = 0;
- idx = GET_REC_PACK_TYPE_INDEX(smsi->smsi_flags);
- return smsi->smsi_pack_rec[idx];
-}
+ if (!(le32_to_cpu(handle->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) {
+ CERROR("log is not plain\n");
+ RETURN(-EINVAL);
+ }
-static int smfs_post_kml_rec(struct inode *dir, void *de, void *data1,
- void *data2, int op);
+ if (le32_to_cpu(rec->lrh_type) == LLOG_GEN_REC) {
+ struct llog_cookie cookie;
-static int smfs_rec_post_hook(struct inode *inode, void *dentry,
- void *data1, void *data2, int op, void *handle)
-{
- int rc = 0;
- ENTRY;
+ cookie.lgc_lgl = handle->lgh_id;
+ cookie.lgc_index = le32_to_cpu(rec->lrh_index);
- if (smfs_do_rec(inode))
- rc = smfs_post_kml_rec(inode, dentry, data1, data2, op);
-
- RETURN(rc);
-}
+ llog_cancel(handle->lgh_ctxt, 1, &cookie, 0, NULL);
+ RETURN(LLOG_PROC_BREAK);
+ }
-#define KML_HOOK "kml_hook"
+ if (le32_to_cpu(rec->lrh_type) != SMFS_UPDATE_REC)
+ RETURN(-EINVAL);
-int smfs_rec_init(struct super_block *sb)
-{
- int rc = 0;
- struct smfs_super_info *smfs_info = S2SMI(sb);
- struct smfs_hook_ops *rec_hops = NULL;
- ENTRY;
+ rec_buf = (char*) (rec + 1);
- SMFS_SET_REC(smfs_info);
+ if (!S2SMI(args->sr_sb)->smsi_ctxt)
+ GOTO(exit, rc = -ENODEV);
- rc = ost_rec_pack_init(smfs_info);
- if (rc)
- return rc;
-
- rc = mds_rec_pack_init(smfs_info);
- if (rc)
- return rc;
-
- rec_hops = smfs_alloc_hook_ops(KML_HOOK, NULL, smfs_rec_post_hook);
- if (!rec_hops) {
- RETURN(-ENOMEM);
+ push_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
+#if 0
+ /*FIXME later should first unpack the rec,
+ * then call lvfs_reint or lvfs_undo
+ * kml rec format has changed lvfs_reint lvfs_undo should
+ * be rewrite FIXME later*/
+ if (SMFS_DO_REINT_REC(args->sr_flags))
+ rc = lvfs_reint(args->sr_sb, rec_buf);
+ else
+ rc = lvfs_undo(args->sr_sb, rec_buf);
+#endif
+ if (!rc && !SMFS_DO_REC_ALL(args->sr_flags)) {
+ args->sr_count --;
+ if (args->sr_count == 0)
+ rc = LLOG_PROC_BREAK;
}
- rc = smfs_register_hook_ops(smfs_info, rec_hops);
- if (rc && rec_hops) {
- smfs_unregister_hook_ops(smfs_info, rec_hops->smh_name);
- smfs_free_hook_ops(rec_hops);
- }
+ pop_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
+exit:
RETURN(rc);
}
-int smfs_rec_cleanup(struct smfs_super_info *smfs_info)
+static smfs_pack_rec_func smfs_get_rec_pack_type(struct super_block *sb)
{
- struct smfs_hook_ops *rec_hops;
- int rc = 0;
- ENTRY;
+ int idx = 0;
+ struct smfs_super_info *smsi = S2SMI(sb);
- rec_hops = smfs_unregister_hook_ops(smfs_info, KML_HOOK);
- smfs_free_hook_ops(rec_hops);
- SMFS_CLEAN_REC(smfs_info);
-
- RETURN(rc);
+ idx = GET_REC_PACK_TYPE_INDEX(smsi->smsi_flags);
+ return smsi->smsi_pack_rec[idx];
}
static inline void
}
EXPORT_SYMBOL(smfs_rec_unpack);
-int smfs_start_rec(struct super_block *sb, struct vfsmount *mnt)
-{
- struct dentry *dentry;
- struct lvfs_run_ctxt saved;
- int rc = 0;
- ENTRY;
-
- if (SMFS_INIT_REC(S2SMI(sb)) ||
- (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
- RETURN(rc);
-
- rc = smfs_llog_setup(sb, mnt);
- if (rc)
- RETURN(rc);
- push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
- dentry = simple_mkdir(current->fs->pwd, "DELETE", 0777, 1);
- if (IS_ERR(dentry)) {
- rc = PTR_ERR(dentry);
- CERROR("cannot create DELETE directory: rc = %d\n", rc);
- GOTO(err_exit, rc = -EINVAL);
- }
- S2SMI(sb)->smsi_delete_dir = dentry;
-
- if (!rc)
- SMFS_SET_INIT_REC(S2SMI(sb));
-exit:
- pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
- RETURN(rc);
-err_exit:
- if (S2SMI(sb)->smsi_ctxt)
- OBD_FREE(S2SMI(sb)->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
- goto exit;
-}
-EXPORT_SYMBOL(smfs_start_rec);
-
-int smfs_post_setup(struct super_block *sb, struct vfsmount *mnt)
-{
- struct lvfs_run_ctxt *current_ctxt = NULL;
- struct smfs_super_info *smb = S2SMI(sb);
- ENTRY;
-
- 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;
-
- RETURN(0);
-}
-EXPORT_SYMBOL(smfs_post_setup);
-
-int smfs_post_cleanup(struct super_block *sb)
-{
- struct smfs_super_info *smb = S2SMI(sb);
- ENTRY;
-
- if (smb->smsi_ctxt)
- OBD_FREE(S2SMI(sb)->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
- RETURN(0);
-}
-EXPORT_SYMBOL(smfs_post_cleanup);
-
-int smfs_stop_rec(struct super_block *sb)
-{
- int rc = 0;
- ENTRY;
-
- if (!SMFS_INIT_REC(S2SMI(sb)) ||
- (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
- RETURN(rc);
-
- rc = smfs_llog_cleanup(sb);
-
- SMFS_CLEAN_INIT_REC(S2SMI(sb));
-
- if (S2SMI(sb)->smsi_delete_dir) {
- l_dput(S2SMI(sb)->smsi_delete_dir);
- S2SMI(sb)->smsi_delete_dir = NULL;
- }
- RETURN(rc);
-}
-EXPORT_SYMBOL(smfs_stop_rec);
-
int smfs_write_extents(struct inode *dir, struct dentry *dentry,
unsigned long from, unsigned long num)
{
}
EXPORT_SYMBOL(smfs_rec_setattr);
-int smfs_rec_md(struct inode *inode, void *lmm, int lmm_size,
- enum ea_type type)
+int smfs_rec_md(struct inode *inode, void *lmm, int lmm_size)
{
char *set_lmm = NULL;
- int rc = 0;
+ int rc = 0;
ENTRY;
if (!SMFS_DO_REC(S2SMI(inode->i_sb)))
RETURN(0);
if (lmm) {
- int size = lmm_size + sizeof(lmm_size) +
- sizeof(type);
-
- OBD_ALLOC(set_lmm, size);
+ OBD_ALLOC(set_lmm, lmm_size + sizeof(lmm_size));
if (!set_lmm)
RETURN(-ENOMEM);
-
memcpy(set_lmm, &lmm_size, sizeof(lmm_size));
- memcpy(set_lmm + sizeof(lmm_size), &type, sizeof(type));
- memcpy(set_lmm + sizeof(lmm_size) + sizeof(type), lmm, lmm_size);
-
+ memcpy(set_lmm + sizeof(lmm_size), lmm, lmm_size);
rc = smfs_post_rec_setattr(inode, NULL, NULL, set_lmm);
if (rc) {
- CERROR("Error: Record md for inode %lu rc = %d\n",
+ CERROR("Error: Record md for inode %lu rc=%d\n",
inode->i_ino, rc);
}
- OBD_FREE(set_lmm, size);
}
+ if (set_lmm)
+ OBD_FREE(set_lmm, lmm_size + sizeof(lmm_size));
RETURN(rc);
}
EXPORT_SYMBOL(smfs_rec_md);
args.sr_count = count;
args.sr_data = dir;
args.sr_flags = flags ;
- ctxt = S2SMI(sb)->smsi_rec_log;
+ ctxt = S2SMI(sb)->smsi_kml_log;
loghandle = ctxt->loc_handle;
if (count == 0) {
}
int smfs_post_rec_setattr(struct inode *inode, struct dentry *dentry,
- void *data1, void *data2)
+ void *data1, void *data2)
{
+ struct smfs_super_info *sinfo;
struct iattr *attr = (struct iattr *)data1;
+ char *buffer = NULL, *pbuf;
int rc = 0, length = 0, buf_len = 0;
- struct smfs_super_info *sinfo;
- char *buffer = NULL, *pbuf;
ENTRY;
sinfo = S2SMI(inode->i_sb);
RETURN(rc);
}
-typedef int (*post_kml_rec)(struct inode *dir, struct dentry *dentry,
- void *data1, void *data2);
+/* new plugin API */
+struct kml_priv {
+ struct dentry * kml_llog_dir;
+};
+
+static int kml_create(struct inode * inode, void *arg)
+{
+ struct hook_msg * msg = arg;
+ return smfs_post_rec_create(inode, msg->dentry, NULL, NULL);
+}
+
+static int kml_link(struct inode * inode, void *arg)
+{
+ struct hook_link_msg * msg = arg;
+ return smfs_post_rec_link(inode, msg->dentry, msg->new_dentry, NULL);
+}
+
+static int kml_unlink(struct inode * inode, void *arg)
+{
+ struct hook_unlink_msg * msg = arg;
+ return smfs_post_rec_unlink(inode, msg->dentry, &msg->mode, NULL);
+}
+
+static int kml_symlink(struct inode * inode, void *arg)
+{
+ struct hook_symlink_msg * msg = arg;
+ return smfs_post_rec_create(inode, msg->dentry, &msg->tgt_len,
+ msg->symname);
+}
+
+static int kml_rename(struct inode * inode, void *arg)
+{
+ struct hook_rename_msg * msg = arg;
+ return smfs_post_rec_rename(inode, msg->dentry, msg->new_dir,
+ msg->new_dentry);
+}
+
+static int kml_setattr(struct inode * inode, void *arg)
+{
+ struct hook_setattr_msg * msg = arg;
+ return smfs_post_rec_setattr(inode, msg->dentry, msg->attr, NULL);
+}
+
+static int kml_write(struct inode * inode, void *arg)
+{
+ struct hook_write_msg * msg = arg;
+ return smfs_post_rec_write(inode, msg->dentry, &msg->count, &msg->pos);
+}
-static post_kml_rec smfs_kml_post[HOOK_MAX + 1] = {
- [HOOK_CREATE] smfs_post_rec_create,
+typedef int (*post_kml_op)(struct inode * inode, void *msg);
+static post_kml_op smfs_kml_post[HOOK_MAX] = {
+ [HOOK_CREATE] kml_create,
[HOOK_LOOKUP] NULL,
- [HOOK_LINK] smfs_post_rec_link,
- [HOOK_UNLINK] smfs_post_rec_unlink,
- [HOOK_SYMLINK] smfs_post_rec_create,
- [HOOK_MKDIR] smfs_post_rec_create,
- [HOOK_RMDIR] smfs_post_rec_unlink,
- [HOOK_MKNOD] smfs_post_rec_create,
- [HOOK_RENAME] smfs_post_rec_rename,
- [HOOK_SETATTR] smfs_post_rec_setattr,
- [HOOK_WRITE] smfs_post_rec_write,
+ [HOOK_LINK] kml_link,
+ [HOOK_UNLINK] kml_unlink,
+ [HOOK_SYMLINK] kml_symlink,
+ [HOOK_MKDIR] kml_create,
+ [HOOK_RMDIR] kml_unlink,
+ [HOOK_MKNOD] kml_create,
+ [HOOK_RENAME] kml_rename,
+ [HOOK_SETATTR] kml_setattr,
+ [HOOK_WRITE] kml_write,
[HOOK_READDIR] NULL,
};
-static int smfs_post_kml_rec(struct inode *dir, void *de, void *data1,
- void *data2, int op)
+
+static int smfs_kml_post_op(int code, struct inode * inode,
+ void * msg, int ret, void * priv)
{
- if (smfs_kml_post[op]) {
- struct dentry *dentry = (struct dentry *)de;
- return smfs_kml_post[op](dir, dentry, data1, data2);
+ int rc = 0;
+
+ ENTRY;
+ CDEBUG(D_INODE,"KML: inode %lu, code: %u\n", inode->i_ino, code);
+ //KML don't handle failed ops
+ if (ret)
+ RETURN(0);
+
+ if (smfs_kml_post[code]) {
+ rc = smfs_kml_post[code](inode, msg);
}
+
+ RETURN(rc);
+}
+
+/* Helpers */
+static int smfs_exit_kml(struct super_block *sb, void * arg, struct kml_priv * priv)
+{
+ ENTRY;
+
+ smfs_deregister_plugin(sb, SMFS_PLG_KML);
+
+ EXIT;
return 0;
}
+
+static int smfs_trans_kml (struct super_block *sb, void *arg,
+ struct kml_priv * priv)
+{
+ int size;
+
+ ENTRY;
+
+ size = 20;//LDISKFS_INDEX_EXTRA_TRANS_BLOCKS+LDISKFS_DATA_TRANS_BLOCKS;
+
+ RETURN(size);
+}
+
+static int smfs_start_kml(struct super_block *sb, void *arg,
+ struct kml_priv * kml_p)
+{
+ int rc = 0;
+ struct smfs_super_info * smb = S2SMI(sb);
+ struct llog_ctxt **ctxt = &smb->smsi_kml_log;
+
+ ENTRY;
+ //is plugin already activated
+ if (SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
+ RETURN(0);
+
+ //this will do OBD_ALLOC() for ctxt
+ rc = llog_catalog_setup(ctxt, KML_LOG_NAME, smb->smsi_exp,
+ smb->smsi_ctxt, smb->sm_fsfilt,
+ smb->smsi_logs_dir,
+ smb->smsi_objects_dir);
+
+ if (rc) {
+ CERROR("Failed to initialize kml log list catalog %d\n", rc);
+ RETURN(rc);
+ }
+
+ (*ctxt)->llog_proc_cb = smfs_llog_process_rec_cb;
+
+ SMFS_SET(smb->plg_flags, SMFS_PLG_KML);
+
+ RETURN(0);
+}
+
+int smfs_stop_kml(struct super_block *sb, void *arg,
+ struct kml_priv * kml_p)
+{
+ struct smfs_super_info * smb = S2SMI(sb);
+ struct llog_ctxt *ctxt = smb->smsi_kml_log;
+ ENTRY;
+
+ if (!SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
+ RETURN(0);
+
+ SMFS_CLEAR(smb->plg_flags, SMFS_PLG_KML);
+
+ llog_catalog_cleanup(ctxt);
+ OBD_FREE(ctxt, sizeof(*ctxt));
+
+ RETURN(0);
+}
+
+typedef int (*kml_helper)(struct super_block * sb, void *msg, struct kml_priv *);
+static kml_helper smfs_kml_helpers[PLG_HELPER_MAX] = {
+ [PLG_EXIT] smfs_exit_kml,
+ [PLG_START] smfs_start_kml,
+ [PLG_STOP] smfs_stop_kml,
+ [PLG_TRANS_SIZE] smfs_trans_kml,
+ [PLG_TEST_INODE] NULL,
+ [PLG_SET_INODE] NULL,
+};
+
+static int smfs_kml_help_op(int code, struct super_block * sb,
+ void * arg, void * priv)
+{
+ int rc = 0;
+ ENTRY;
+ if (smfs_kml_helpers[code])
+ rc = smfs_kml_helpers[code](sb, arg, (struct kml_priv *) priv);
+ RETURN(rc);
+}
+
+int smfs_init_kml(struct super_block *sb)
+{
+ int rc = 0;
+ struct smfs_super_info *smb = S2SMI(sb);
+ struct smfs_plugin plg = {
+ .plg_type = SMFS_PLG_KML,
+ .plg_pre_op = NULL,
+ .plg_post_op = &smfs_kml_post_op,
+ .plg_helper = &smfs_kml_help_op,
+ .plg_private = NULL,
+ };
+
+ ENTRY;
+
+ rc = ost_rec_pack_init(smb);
+ if (rc)
+ return rc;
+
+ rc = mds_rec_pack_init(smb);
+ if (rc)
+ return rc;
+
+ rc = smfs_register_plugin(sb, &plg);
+
+ RETURN(rc);
+}
+
+
#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, "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
+ *devstr = strcpy(ret + strlen(ret) + 1, *devstr);//, strlen(*devstr));
+ *namestr = strcpy(*devstr + strlen(*devstr) + 1, *namestr);//, strlen(*namestr));
+
+ OBD_FREE(temp, strlen(data) + 1);
+
+ RETURN(0);
+}
static struct smfs_super_info *smfs_init_smb(struct super_block *sb)
{
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);
}
+int smfs_post_setup(struct super_block *sb, struct vfsmount *mnt)
+{
+ struct lvfs_run_ctxt saved, *current_ctxt = NULL;
+ struct smfs_super_info *smb = S2SMI(sb);
+ int rc = 0;
+
+ ENTRY;
+
+ 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(sb, mnt);
+ if (!rc) {
+ rc = SMFS_PLG_HELP(sb, PLG_START, NULL);
+ }
+
+ pop_ctxt(&saved, smb->smsi_ctxt, NULL);
+
+ 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(sb);
+ 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",
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);
+
+ 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)
-{
- struct list_head *hlist = &smb->smsi_hook_list;
- ENTRY;
-
- while (!list_empty(hlist)) {
- struct smfs_hook_ops *smfs_hops;
-
- 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)
+static void smfs_remove_plugins(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)
-{
+ SMFS_PLG_HELP(sb, PLG_EXIT, (void*)sb);
- 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);
+ 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 *);
-extern void cleanup_option(void);
-
int smfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct inode *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;
+ char *opts = NULL;
+ int err = 0;
+ int flags = 0;
ino_t root_ino;
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)");
+ CERROR("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;
-
- 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);
+ lock_kernel();
+ OBD_ALLOC(opts, strlen(data) + 1);
+ if (!opts) {
+ err = -ENOMEM;
+ goto out_err;
}
-
+
+ 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;
}
+ CERROR("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;
}
+ OBD_FREE(opts, strlen(data) + 1);
+ opts = NULL;
+
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);
sb->s_op->read_inode, root_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);
- }
#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);
-}
+ if (smb->smsi_mnt)
+ smfs_umount_cache(smb);
-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 (opts)
+ OBD_FREE(opts, strlen(data) + 1);
- found = list_entry(p, typeof(*found), smh_list);
- if (!memcmp(found->smh_name, name, strlen(name))) {
- list_del(p);
- RETURN(found);
- }
- }
-
- RETURN(NULL);
+ smfs_cleanup_smb(smb);
+ unlock_kernel();
+ RETURN(err);
}
void *smfs_trans_start(struct inode *inode, int op, void *desc_private)
if (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 * new_plugin)
{
+ struct smfs_super_info * smb = S2SMI(sb);
struct smfs_plugin * plg = NULL;
struct list_head * plist = &S2SMI(sb)->smsi_plg_list;
}
}
+
+ if (SMFS_IS(smb->smsi_flags, new_plugin->plg_type)) {
+ CWARN("Plugin is already registered\n");
+ RETURN(-EEXIST);
+ }
+
OBD_ALLOC(plg, sizeof(*plg));
if (!plg) {
CWARN("Cannot allocate memory for plugin\n");
memcpy(plg, new_plugin, sizeof(*plg));
list_add_tail(&plg->plg_list, plist);
-
+
RETURN(0);
}
-void * smfs_deregister_plugin(struct super_block * sb, int type)
+void * 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;
ENTRY;
+
list_for_each_entry(plg, plist, plg_list) {
if (plg->plg_type == type) {
list_del(&plg->plg_list);
RETURN(priv);
}
+void smfs_pre_hook (struct inode * inode, int 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;
+
+ //ENTRY;
+ LASSERT(op < HOOK_MAX);
+ //call hook operations
+ 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 not exclusion
+ 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);
+ }
+
+ //EXIT;
+}
+
+void smfs_post_hook (struct inode * inode, int 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;
+
+ 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 not exclusion
+ 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);
+ }
+
+ //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;
+ int rc = 0;
+
+ ENTRY;
+ LASSERT(op < PLG_HELPER_MAX);
+ //call hook operations
+ list_for_each_entry(plg, hlist, plg_list) {
+ if (plg->plg_helper)
+ rc += plg->plg_helper(op, sb, msg, plg->plg_private);
+ }
+
+ EXIT;
+
+ return rc;
+}
+
#include <linux/lvfs.h>
#include "smfs_internal.h"
-
-static int smfs_llog_process_rec_cb(struct llog_handle *handle,
- struct llog_rec_hdr *rec, void *data)
-{
- char *rec_buf ;
- struct smfs_proc_args *args = (struct smfs_proc_args *)data;
- struct lvfs_run_ctxt saved;
- int rc = 0;
-
- if (!(le32_to_cpu(handle->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) {
- CERROR("log is not plain\n");
- RETURN(-EINVAL);
- }
-
- if (le32_to_cpu(rec->lrh_type) == LLOG_GEN_REC) {
- struct llog_cookie cookie;
-
- cookie.lgc_lgl = handle->lgh_id;
- cookie.lgc_index = le32_to_cpu(rec->lrh_index);
-
- llog_cancel(handle->lgh_ctxt, 1, &cookie, 0, NULL);
- RETURN(LLOG_PROC_BREAK);
- }
-
- if (le32_to_cpu(rec->lrh_type) != SMFS_UPDATE_REC)
- RETURN(-EINVAL);
-
- rec_buf = (char*) (rec + 1);
-
- if (!S2SMI(args->sr_sb)->smsi_ctxt)
- GOTO(exit, rc = -ENODEV);
-
- push_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
-#if 0
- /*FIXME later should first unpack the rec,
- * then call lvfs_reint or lvfs_undo
- * kml rec format has changed lvfs_reint lvfs_undo should
- * be rewrite FIXME later*/
- if (SMFS_DO_REINT_REC(args->sr_flags))
- rc = lvfs_reint(args->sr_sb, rec_buf);
- else
- rc = lvfs_undo(args->sr_sb, rec_buf);
-#endif
- if (!rc && !SMFS_DO_REC_ALL(args->sr_flags)) {
- args->sr_count --;
- if (args->sr_count == 0)
- rc = LLOG_PROC_BREAK;
- }
- pop_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
-exit:
- RETURN(rc);
-}
-
int smfs_llog_setup(struct super_block *sb, struct vfsmount *mnt)
{
- struct llog_ctxt **ctxt = &(S2SMI(sb)->smsi_rec_log);
- struct lvfs_run_ctxt saved;
- struct dentry *dentry;
- int rc = 0, rc2;
+ struct dentry *dentry = NULL;
+ int rc = 0;
/* create OBJECTS and LOGS for writing logs */
ENTRY;
LASSERT(mnt);
- push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
+ //push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
dentry = simple_mkdir(current->fs->pwd, "LOGS", 0777, 1);
if (IS_ERR(dentry)) {
rc = PTR_ERR(dentry);
CERROR("cannot create LOGS directory: rc = %d\n", rc);
- GOTO(exit, rc = -EINVAL);
+ rc = -EINVAL;
+ goto exit;
}
S2SMI(sb)->smsi_logs_dir = dentry;
+ SMFS_SET(I2SMI(dentry->d_inode)->smi_flags, SMFS_PLG_ALL);
+
dentry = simple_mkdir(current->fs->pwd, "OBJECTS", 0777, 1);
if (IS_ERR(dentry)) {
rc = PTR_ERR(dentry);
CERROR("cannot create OBJECTS directory: rc = %d\n", rc);
- GOTO(exit, rc = -EINVAL);
+ rc = -EINVAL;
+ goto exit;
}
S2SMI(sb)->smsi_objects_dir = dentry;
+ SMFS_SET(I2SMI(dentry->d_inode)->smi_flags, SMFS_PLG_ALL);
/* write log will not write to KML, cleanup kml flags */
- SMFS_CLEAN_INODE_REC(S2SMI(sb)->smsi_objects_dir->d_inode);
- SMFS_CLEAN_INODE_REC(S2SMI(sb)->smsi_logs_dir->d_inode);
+ //SMFS_CLEAN_INODE_REC(S2SMI(sb)->smsi_objects_dir->d_inode);
+ //SMFS_CLEAN_INODE_REC(S2SMI(sb)->smsi_logs_dir->d_inode);
/* log create does not call cache hooks, cleanup hook flags */
- SMFS_CLEAN_INODE_CACHE_HOOK(S2SMI(sb)->smsi_objects_dir->d_inode);
- SMFS_CLEAN_INODE_CACHE_HOOK(S2SMI(sb)->smsi_logs_dir->d_inode);
+ //SMFS_CLEAN_INODE_CACHE_HOOK(S2SMI(sb)->smsi_objects_dir->d_inode);
+ //SMFS_CLEAN_INODE_CACHE_HOOK(S2SMI(sb)->smsi_logs_dir->d_inode);
- if (SMFS_DO_REC(S2SMI(sb))) {
- rc = llog_catalog_setup(ctxt, KML_LOG_NAME, S2SMI(sb)->smsi_exp,
- S2SMI(sb)->smsi_ctxt, S2SMI(sb)->sm_fsfilt,
- S2SMI(sb)->smsi_logs_dir,
- S2SMI(sb)->smsi_objects_dir);
- (*ctxt)->llog_proc_cb = smfs_llog_process_rec_cb;
- }
-
- if (SMFS_CACHE_HOOK(S2SMI(sb))) {
+
+ /*if (SMFS_CACHE_HOOK(S2SMI(sb))) {
rc2 = cache_space_hook_setup(sb);
if (!rc && rc2)
rc = rc2;
- }
+ }*/
exit:
- pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
+ //pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
RETURN(rc);
}
int smfs_llog_cleanup(struct super_block *sb)
{
- struct llog_ctxt *ctxt = S2SMI(sb)->smsi_rec_log;
- int rc = 0, rc2;
ENTRY;
+ /*
if (SMFS_CACHE_HOOK(S2SMI(sb)))
rc = cache_space_hook_cleanup();
if (!rc)
rc = rc2;
}
-
+ */
if (S2SMI(sb)->smsi_logs_dir) {
l_dput(S2SMI(sb)->smsi_logs_dir);
S2SMI(sb)->smsi_logs_dir = NULL;
l_dput(S2SMI(sb)->smsi_objects_dir);
S2SMI(sb)->smsi_objects_dir = NULL;
}
- RETURN(rc);
+ RETURN(0);
}
int smfs_llog_add_rec(struct smfs_super_info *sinfo, void *data, int data_size)
rec.lrh_len = size_round(data_size);
rec.lrh_type = SMFS_UPDATE_REC;
- rc = llog_add(sinfo->smsi_rec_log, &rec, data, NULL, 0, NULL, NULL, NULL);
+ rc = llog_add(sinfo->smsi_kml_log, &rec, data, NULL, 0, NULL, NULL, NULL);
if (rc != 1) {
CERROR("error adding kml rec: %d\n", rc);
RETURN(-EINVAL);
}
RETURN(0);
}
+