Whamcloud - gitweb
b=6274
[fs/lustre-release.git] / lustre / smfs / kml.c
index c57163f..338b995 100644 (file)
@@ -53,67 +53,70 @@ do {                                            \
         pbuf = buffer + length;                 \
 } while (0)
 
-static smfs_pack_rec_func smfs_get_rec_pack_type(struct super_block *sb)
-{
-        struct smfs_super_info *smsi = S2SMI(sb);
 
-        int index = GET_REC_PACK_TYPE_INDEX(smsi->smsi_flags);
+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;
 
-        return smsi->smsi_pack_rec[index];
-}
+        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"
-int smfs_rec_init(struct super_block *sb)
-{
-        struct smfs_super_info *smfs_info = S2SMI(sb);
-        struct smfs_hook_ops   *rec_hops = NULL;
-        int rc = 0;
+        if (le32_to_cpu(rec->lrh_type) != SMFS_UPDATE_REC)
+                RETURN(-EINVAL);
 
-        SMFS_SET_REC(smfs_info);
+        rec_buf = (char*) (rec + 1);
 
-        ost_rec_pack_init(smfs_info);
-        mds_rec_pack_init(smfs_info);
+        if (!S2SMI(args->sr_sb)->smsi_ctxt)
+                GOTO(exit, rc = -ENODEV);
 
-        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;
+        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 copy_inode_attr(struct iattr *iattr, struct inode *inode)
+static inline void
+copy_inode_attr(struct iattr *iattr, struct inode *inode)
 {
         iattr->ia_mode = inode->i_mode;
         iattr->ia_uid  = inode->i_uid;
@@ -129,6 +132,7 @@ static inline int unpack_rec_data(char **p_buffer, int *size,
 {
         int args_len = 0;
         int rc = 0;
+        ENTRY;
 
         if (args_data)
                 args_len = strlen(args_data);
@@ -139,11 +143,12 @@ static inline int unpack_rec_data(char **p_buffer, int *size,
         OBD_ALLOC(*p_buffer, *size + args_len + 1);
         if (!*p_buffer)
                 RETURN(-ENOMEM);
-        /*First copy reint dir */
+
+        /* first copy reint dir. */
         if (args_data)
                 memcpy(*p_buffer, args_data, args_len);
 
-        /*then copy the node name */
+        /* then copy the node name. */
         memcpy(*p_buffer + args_len,
                       (in_data + sizeof(int)), *size);
 
@@ -157,99 +162,13 @@ int smfs_rec_unpack(struct smfs_proc_args *args, char *record,
 {
         int offset = *(int *)(record);
         char *tmp = record + offset + sizeof(int);
-        int rc = 0;
+
         *opcode = *(int *)tmp;
         *pbuf = tmp + sizeof(*opcode);
-        RETURN(rc);
+        return 0;
 }
 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);
-        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;
-
-        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)
 {
@@ -264,12 +183,15 @@ int smfs_rec_setattr(struct inode *dir, struct dentry *dentry,
 }
 EXPORT_SYMBOL(smfs_rec_setattr);
 
-int smfs_rec_md(struct inode *inode, void * lmm, int lmm_size)
+int smfs_rec_md(struct inode *inode, void *lmm, int lmm_size)
 {
         char *set_lmm = NULL;
         int  rc = 0;
         ENTRY;
 
+        if (!SMFS_DO_REC(S2SMI(inode->i_sb)))
+                RETURN(0);
+
         if (lmm) {
                 OBD_ALLOC(set_lmm, lmm_size + sizeof(lmm_size));
                 if (!set_lmm)
@@ -284,7 +206,7 @@ int smfs_rec_md(struct inode *inode, void * lmm, int lmm_size)
         }
         if (set_lmm)
                 OBD_FREE(set_lmm, lmm_size + sizeof(lmm_size));
-        return rc;
+        RETURN(rc);
 }
 EXPORT_SYMBOL(smfs_rec_md);
 
@@ -301,6 +223,7 @@ int smfs_process_rec(struct super_block *sb,
         struct llog_handle *loghandle;
         struct smfs_proc_args args;
         int rc = 0;
+        ENTRY;
 
         if (!SMFS_INIT_REC(S2SMI(sb))) {
                 CWARN("Did not start up rec server \n");
@@ -312,16 +235,15 @@ int smfs_process_rec(struct super_block *sb,
         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) {
                 if (SMFS_DO_REINT_REC(flags)) {
                         struct llog_gen_rec *lgr;
 
-                        /*For reint rec, we need insert
-                          *a gen rec to identify the end
-                          *of the rec.*/
+                        /* for reint rec, we need insert a gen rec to identify
+                         * the end of the rec.*/
                         OBD_ALLOC(lgr, sizeof(*lgr));
                         if (!lgr)
                                 RETURN(-ENOMEM);
@@ -401,6 +323,8 @@ static int smfs_log_path(struct super_block *sb,
         char *p_name = buffer + sizeof(int);
         char *name = NULL;
         int namelen = 0;
+        ENTRY;
+
         if (dentry) {
                 name = smfs_path(dentry, root, p_name, buffer_len - sizeof(int));
                 namelen = cpu_to_le32(strlen(p_name));
@@ -422,22 +346,20 @@ static int smfs_pack_rec (char *buffer, struct dentry *dentry,
                           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;
+        if (!pack_func)
+                return 0;
+        return pack_func(buffer, dentry, dir, data1, data2, op);
 }
 
-int smfs_post_rec_create(struct inode *dir, struct dentry *dentry, void *data1, 
-                         void *data2)
+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;
+        ENTRY;
         
         sinfo = S2SMI(dentry->d_inode->i_sb);
         if (!sinfo)
@@ -472,10 +394,11 @@ exit:
 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;
+        struct dentry *new_dentry = (struct dentry *)data1;
         int rc = 0, length = 0, buf_len = 0;
+        char *buffer = NULL, *pbuf = NULL;
+        struct smfs_super_info *sinfo;
+        ENTRY;
         
         sinfo = S2SMI(dir->i_sb);
         if (!sinfo)
@@ -486,6 +409,7 @@ static int smfs_post_rec_link(struct inode *dir, struct dentry *dentry,
         
         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);
@@ -493,13 +417,13 @@ static int smfs_post_rec_link(struct inode *dir, struct dentry *dentry,
         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);
+        rc = smfs_pack_rec(pbuf, dentry, dir, dentry, 
+                           new_dentry, REINT_LINK);
         if (rc <= 0)
                 GOTO(exit, rc);
-        else
-                length += rc;
-        rc = smfs_llog_add_rec(sinfo, (void*)buffer, length); 
+        
+        length += rc;
+        rc = smfs_llog_add_rec(sinfo, (void *)buffer, length); 
 exit:
         if (buffer)
                 OBD_FREE(buffer, PAGE_SIZE);        
@@ -514,6 +438,7 @@ static int smfs_post_rec_unlink(struct inode *dir, struct dentry *dentry,
         int mode = *((int*)data1);
         char   *buffer = NULL, *pbuf = NULL;
         int  length = 0, rc = 0, buf_len = 0;
+        ENTRY;
          
         sinfo = S2SMI(dentry->d_inode->i_sb);
         if (!sinfo)
@@ -554,6 +479,7 @@ static int smfs_post_rec_rename(struct inode *dir, struct dentry *dentry,
         struct dentry *new_dentry = (struct dentry *)data2;
         char *buffer = NULL, *pbuf = NULL;
         int rc = 0, length = 0, buf_len = 0;
+        ENTRY;
         
         sinfo = S2SMI(dir->i_sb);
         if (!sinfo)
@@ -571,8 +497,9 @@ static int smfs_post_rec_rename(struct inode *dir, struct dentry *dentry,
 
         pbuf += rc; 
         length += rc;
-        buf_len -= rc;         
-        /*record new_dentry path*/        
+        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);
@@ -597,6 +524,7 @@ 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;
+        ENTRY;
         
         if (SMFS_INODE_OVER_WRITE(inode))
                 RETURN(rc);
@@ -610,6 +538,7 @@ 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;
+        ENTRY;
         
         rc = fsfilt->fs_remove_extents_ea(inode, OFF2BLKS(from, inode), 
                                           SIZE2BLKS(num, inode));        
@@ -621,6 +550,7 @@ static int smfs_remove_all_extents_ea(struct inode *inode)
 {
         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
         int rc = 0;
+        ENTRY;
         
         rc = fsfilt->fs_remove_extents_ea(inode, 0, 0xffffffff);        
         RETURN(rc);
@@ -629,6 +559,7 @@ static int  smfs_init_extents_ea(struct inode *inode)
 {
         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
         int rc = 0;
+        ENTRY;
         
         rc = fsfilt->fs_init_extents_ea(inode);        
         
@@ -639,6 +570,7 @@ 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;
+        ENTRY;
 
         if (SMFS_INODE_OVER_WRITE(inode))
                 RETURN(rc);
@@ -671,6 +603,7 @@ int smfs_post_rec_setattr(struct inode *inode, struct dentry *dentry,
         struct iattr *attr = (struct iattr *)data1;
         char   *buffer = NULL, *pbuf;
         int rc = 0, length = 0, buf_len = 0;
+        ENTRY;
 
         sinfo = S2SMI(inode->i_sb);
         if (!sinfo)
@@ -716,15 +649,17 @@ exit:
 static int all_blocks_present_ea(struct inode *inode)
 {
         int rc = 0;
-        
+        ENTRY;
         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;
+        ENTRY;
         
         if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) && 
             !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) {
@@ -783,30 +718,205 @@ exit:
         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 post_kml_rec smfs_kml_post[HOOK_MAX + 1] = {
-        [HOOK_CREATE]  smfs_post_rec_create,
+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);
+}
+
+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)
-{
-        if (smfs_kml_post[op]) {
-                struct dentry *dentry = (struct dentry *)de;
 
-                return smfs_kml_post[op](dir, dentry, data1, data2);
+static int smfs_kml_post_op(int code, struct inode * inode,
+                            void * msg, int ret, void * priv)
+{
+        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);
+}
+
+