Whamcloud - gitweb
b=5881
[fs/lustre-release.git] / lustre / smfs / kml.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/smfs/kml.c
5  *  Lustre filesystem abstraction routines
6  *
7  *  Copyright (C) 2004 Cluster File Systems, Inc.
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   Lustre is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with Lustre; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24 #ifndef EXPORT_SYMTAB
25 # define EXPORT_SYMTAB
26 #endif
27
28 #define DEBUG_SUBSYSTEM S_SM
29
30 #include <linux/kmod.h>
31 #include <linux/init.h>
32 #include <linux/fs.h>
33 #include <linux/slab.h>
34 #include <linux/obd_class.h>
35 #include <linux/obd_support.h>
36 #include <linux/lustre_lib.h>
37 #include <linux/lustre_idl.h>
38 #include <linux/lustre_fsfilt.h>
39 #include <linux/lustre_smfs.h>
40 #include "smfs_internal.h"
41
42 #if 0
43 #define KML_BUF_REC_INIT(buffer, pbuf, len)     \
44 do {                                            \
45         pbuf = buffer + sizeof(int);            \
46         len -= sizeof(int);                     \
47 } while (0)
48         
49 #define KML_BUF_REC_END(buffer, length, pbuf)   \
50 do {                                            \
51         int len = length;                       \
52         memcpy(buffer, &len, sizeof(len));      \
53         length += sizeof(int);                  \
54         pbuf = buffer + length;                 \
55 } while (0)
56
57 static int smfs_llog_process_rec_cb(struct llog_handle *handle,
58                                     struct llog_rec_hdr *rec, void *data)
59 {
60         char   *rec_buf ;
61         struct smfs_proc_args *args = (struct smfs_proc_args *)data;
62         struct lvfs_run_ctxt saved;
63         int    rc = 0;
64
65         if (!(le32_to_cpu(handle->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) {
66                 CERROR("log is not plain\n");
67                 RETURN(-EINVAL);
68         }
69
70         if (le32_to_cpu(rec->lrh_type) == LLOG_GEN_REC) {
71                 struct llog_cookie cookie;
72
73                 cookie.lgc_lgl = handle->lgh_id;
74                 cookie.lgc_index = le32_to_cpu(rec->lrh_index);
75
76                 llog_cancel(handle->lgh_ctxt, 1, &cookie, 0, NULL);
77                 RETURN(LLOG_PROC_BREAK);
78         }
79
80         if (le32_to_cpu(rec->lrh_type) != SMFS_UPDATE_REC)
81                 RETURN(-EINVAL);
82
83         rec_buf = (char*) (rec + 1);
84
85         if (!S2SMI(args->sr_sb)->smsi_ctxt)
86                 GOTO(exit, rc = -ENODEV);
87
88         push_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
89 #if 0
90         /*FIXME later should first unpack the rec,
91          * then call lvfs_reint or lvfs_undo
92          * kml rec format has changed lvfs_reint lvfs_undo should
93          * be rewrite FIXME later*/
94         if (SMFS_DO_REINT_REC(args->sr_flags))
95                 rc = lvfs_reint(args->sr_sb, rec_buf);
96         else
97                 rc = lvfs_undo(args->sr_sb, rec_buf);
98 #endif
99         if (!rc && !SMFS_DO_REC_ALL(args->sr_flags)) {
100                 args->sr_count --;
101                 if (args->sr_count == 0)
102                         rc = LLOG_PROC_BREAK;
103         }
104         pop_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
105 exit:
106         RETURN(rc);
107 }
108 #endif
109 #if 0
110 /* not used curently */
111 static smfs_pack_rec_func smfs_get_rec_pack_type(struct super_block *sb)
112 {
113         int idx = 0;
114         struct smfs_super_info *smsi = S2SMI(sb);
115
116         idx = GET_REC_PACK_TYPE_INDEX(smsi->smsi_flags);
117         return smsi->smsi_pack_rec[idx];
118 }
119 #endif
120
121 static inline void
122 copy_inode_attr(struct iattr *iattr, struct inode *inode)
123 {
124         iattr->ia_mode = inode->i_mode;
125         iattr->ia_uid  = inode->i_uid;
126         iattr->ia_gid  = inode->i_gid;
127         iattr->ia_atime = inode->i_atime;
128         iattr->ia_ctime = inode->i_ctime;
129         iattr->ia_mtime = inode->i_mtime;
130         iattr->ia_size = inode->i_size;
131 }
132
133 #if 0
134 static inline int unpack_rec_data(char **p_buffer, int *size,
135                                   char *in_data, char *args_data)
136 {
137         int args_len = 0;
138         int rc = 0;
139         ENTRY;
140
141         if (args_data)
142                 args_len = strlen(args_data);
143
144         *size = *((int*)(in_data));
145         rc = *size + sizeof(int);
146
147         OBD_ALLOC(*p_buffer, *size + args_len + 1);
148         if (!*p_buffer)
149                 RETURN(-ENOMEM);
150
151         /* first copy reint dir. */
152         if (args_data)
153                 memcpy(*p_buffer, args_data, args_len);
154
155         /* then copy the node name. */
156         memcpy(*p_buffer + args_len,
157                       (in_data + sizeof(int)), *size);
158
159         *size += args_len;
160
161         RETURN(rc);
162 }
163 #endif
164
165 int smfs_rec_unpack(struct smfs_proc_args *args, char *record, 
166                     char **pbuf, int *opcode)
167 {
168         //int offset = *(int *)(record);
169         //char *tmp = record + offset + sizeof(int);
170
171         *opcode = *(int *)record;
172         *pbuf = record + sizeof(*opcode);
173         return 0;
174 }
175 EXPORT_SYMBOL(smfs_rec_unpack); /* cmobd/cm_reint.c */
176
177 int smfs_write_extents(struct inode *dir, struct dentry *dentry,
178                        unsigned long from, unsigned long num)
179 {
180         //smfs_post_rec_write(dir, dentry, &from, &num);
181         return 0;
182 }
183 #if 0
184 int smfs_rec_precreate(struct dentry *dentry, int *num, struct obdo *oa)
185 {
186        return smfs_post_rec_create(dentry->d_inode, dentry, num, oa);
187 }
188
189 int smfs_process_rec(struct super_block *sb,
190                      int count, char *dir, int flags)
191 {
192         struct llog_ctxt *ctxt;
193         struct llog_handle *loghandle;
194         struct smfs_proc_args args;
195         int rc = 0;
196         ENTRY;
197
198         if (!SMFS_INIT_REC(S2SMI(sb))) {
199                 CWARN("Did not start up rec server \n");
200                 RETURN(rc);
201         }
202
203         memset(&args, 0, sizeof(struct smfs_proc_args));
204         args.sr_sb = sb;
205         args.sr_count = count;
206         args.sr_data = dir;
207         args.sr_flags = flags ;
208         ctxt = S2SMI(sb)->smsi_kml_log;
209         loghandle = ctxt->loc_handle;
210
211         if (count == 0) {
212                 if (SMFS_DO_REINT_REC(flags)) {
213                         struct llog_gen_rec *lgr;
214
215                         /* for reint rec, we need insert a gen rec to identify
216                          * the end of the rec.*/
217                         OBD_ALLOC(lgr, sizeof(*lgr));
218                         if (!lgr)
219                                 RETURN(-ENOMEM);
220                         lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len = sizeof(*lgr);
221                         lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
222                         lgr->lgr_gen = ctxt->loc_gen;
223                         rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1,
224                                       NULL, NULL, NULL);
225                         OBD_FREE(lgr, sizeof(*lgr));
226                         if (rc != 1)
227                                 RETURN(rc);
228                 }
229         } else {
230                 SET_REC_COUNT_FLAGS(args.sr_flags, SMFS_REC_ALL);
231         }
232         if (loghandle) {
233                 if (SMFS_DO_REINT_REC(flags))
234                         rc = llog_cat_process(loghandle, ctxt->llog_proc_cb,
235                                               (void *)&args);
236                 else
237                         rc = llog_cat_reverse_process(loghandle,
238                                                       ctxt->llog_proc_cb,
239                                                       (void *)&args);
240                 if (rc == LLOG_PROC_BREAK)
241                         rc = 0;
242         }
243         RETURN(rc);
244 }
245
246 /*smfs_path is gotten from intermezzo*/
247 static char* smfs_path(struct dentry *dentry, struct dentry *root, char *buffer,
248                        int buflen)
249 {
250         char * end = buffer + buflen;
251         char * name = buffer;
252         char * buf_end = buffer + buflen;
253         char * retval;
254
255         *--end = '\0';
256         buflen--;
257         /* Get '/' right */
258         retval = end-1;
259         *retval = '/';
260
261         for (;;) {
262                 struct dentry * parent;
263                 int namelen;
264
265                 if (dentry == root)
266                         break;
267                 parent = dentry->d_parent;
268                 if (dentry == parent)
269                         break;
270                 namelen = dentry->d_name.len;
271                 buflen -= namelen + 1;
272                 if (buflen < 0)
273                         break;
274                 end -= namelen;
275                 memcpy(end, dentry->d_name.name, namelen);
276                 *--end = '/';
277                 retval = end;
278                 dentry = parent;
279         }
280         
281         while (end != buf_end) 
282                 *name++ = *end++;
283         *name = '\0'; 
284         return retval;
285 }
286
287 static int smfs_log_path(struct super_block *sb, 
288                          struct dentry *dentry, 
289                          char   *buffer,
290                          int    buffer_len)
291 {
292         struct dentry *root=sb->s_root;
293         char *p_name = buffer + sizeof(int);
294         char *name = NULL;
295         int namelen = 0;
296         ENTRY;
297
298         if (dentry) {
299                 name = smfs_path(dentry, root, p_name, buffer_len - sizeof(int));
300                 namelen = cpu_to_le32(strlen(p_name));
301                 memcpy(buffer, &namelen, sizeof(int));        
302         }
303         namelen += sizeof(int);
304         RETURN(namelen);
305 }
306
307 static int smfs_pack_rec (char *buffer, struct dentry *dentry, 
308                           struct inode *dir, void *data1, 
309                           void *data2, int op)
310
311         smfs_pack_rec_func pack_func;        
312
313         pack_func = smfs_get_rec_pack_type(dir->i_sb);
314         if (!pack_func)
315                 return 0;
316         return pack_func(buffer, dentry, dir, data1, data2, op);
317 }
318
319 static int smfs_insert_extents_ea(struct inode *inode, size_t from, loff_t num)
320 {
321         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
322         int rc = 0;
323         ENTRY;
324         
325         if (SMFS_INODE_OVER_WRITE(inode))
326                 RETURN(rc);
327         
328         rc = fsfilt->fs_insert_extents_ea(inode, OFF2BLKS(from, inode), 
329                                           SIZE2BLKS(num, inode));        
330         RETURN(rc);
331 }
332
333 static int smfs_remove_extents_ea(struct inode *inode, size_t from, loff_t num)
334 {
335         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
336         int rc = 0;
337         ENTRY;
338         
339         rc = fsfilt->fs_remove_extents_ea(inode, OFF2BLKS(from, inode), 
340                                           SIZE2BLKS(num, inode));        
341         
342         RETURN(rc);
343 }
344
345 static int smfs_remove_all_extents_ea(struct inode *inode)
346 {
347         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
348         int rc = 0;
349         ENTRY;
350         
351         rc = fsfilt->fs_remove_extents_ea(inode, 0, 0xffffffff);        
352         RETURN(rc);
353 }
354 static int  smfs_init_extents_ea(struct inode *inode)
355 {
356         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
357         int rc = 0;
358         ENTRY;
359         
360         rc = fsfilt->fs_init_extents_ea(inode);        
361         
362         RETURN(rc);
363 }
364 static int smfs_set_dirty_flags(struct inode *inode, int flags)
365 {
366         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
367         void   *handle;
368         int    rc = 0;
369         ENTRY;
370
371         if (SMFS_INODE_OVER_WRITE(inode))
372                 RETURN(rc);
373         /*FIXME later, the blocks needed in journal here will be recalculated*/
374          handle = smfs_trans_start(inode, FSFILT_OP_SETATTR);
375         if (IS_ERR(handle)) {
376                 CERROR("smfs_set_dirty_flag:no space for transaction\n");
377                 RETURN(-ENOSPC);
378         }
379         if ((!SMFS_INODE_DIRTY_WRITE(inode) && (!SMFS_INODE_OVER_WRITE(inode))) || 
380              ((flags == SMFS_OVER_WRITE) && (SMFS_INODE_DIRTY_WRITE(inode)))) {        
381                 rc = fsfilt->fs_set_xattr(inode, handle, REINT_EXTENTS_FLAGS,
382                                             &flags, sizeof(int));
383                 if (rc)
384                         GOTO(out, rc);
385         }
386         if (flags == SMFS_OVER_WRITE)
387                 SMFS_SET_INODE_OVER_WRITE(inode);
388         else
389                 SMFS_SET_INODE_DIRTY_WRITE(inode);
390 out:
391         smfs_trans_commit(inode, handle, 0);
392         RETURN(rc);
393 }
394
395 static int all_blocks_present_ea(struct inode *inode)
396 {
397         int rc = 0;
398         ENTRY;
399         RETURN(rc);        
400 }
401 #endif
402
403 /* new plugin API */
404 #if 0
405 static int kml_pack_path (char **buf, struct dentry * dentry)
406 {
407         char *pbuf;
408         int length = 0, rc = 0;
409         
410         OBD_ALLOC(*buf, PAGE_SIZE);
411         if (*buf == NULL)
412                 return -ENOMEM;        
413
414         length = PAGE_SIZE;
415         KML_BUF_REC_INIT(*buf, pbuf, length);
416         rc = smfs_log_path(dentry->d_sb, dentry, pbuf, length);
417         if (rc < 0) {
418                 return rc;
419         }
420         
421         length = rc;
422         KML_BUF_REC_END(*buf, length, pbuf);  
423         
424         return length;
425 }
426 #endif
427 static int kml_create(struct inode * inode, void *arg, struct kml_priv * priv) 
428 {
429         struct hook_msg * msg = arg;
430         //return smfs_post_rec_create(inode, msg->dentry, NULL, NULL);
431         struct smfs_super_info *smb = S2SMI(inode->i_sb);
432         char   *buffer = NULL;
433         int rc = 0, length = 0;
434         ENTRY;
435         
436         OBD_ALLOC(buffer, PAGE_SIZE);
437         if (buffer == NULL)
438                 return -ENOMEM;    
439         
440         /*
441         rc = kml_pack_path(&buffer, msg->dentry);
442         if (rc < 0)
443                 goto exit;
444         
445         length = rc;
446         pbuf = buffer + length;
447         */        
448         rc = priv->pack_fn(REINT_CREATE, buffer, msg->dentry, inode,
449                            NULL, NULL);
450         if (rc <= 0)
451                 GOTO(exit, rc);
452         
453         length += rc;
454         rc = smfs_llog_add_rec(smb, (void*)buffer, length); 
455 exit:
456         if (buffer)
457                 OBD_FREE(buffer, PAGE_SIZE);        
458         
459         RETURN(rc);
460 }
461
462 static int kml_link(struct inode *inode, void *arg, struct kml_priv *priv) 
463 {
464         struct hook_link_msg *msg = arg;
465         int rc = 0, length = 0;
466         char *buffer = NULL;
467         ENTRY;
468         
469         OBD_ALLOC(buffer, PAGE_SIZE);
470         if (!buffer)
471                 GOTO(exit, rc = -ENOMEM);
472         
473         rc = priv->pack_fn(REINT_LINK, buffer, msg->dentry, inode, 
474                            msg->dentry, msg->new_dentry);
475         if (rc <= 0)
476                 GOTO(exit, rc);
477         
478         length += rc;
479         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void *)buffer, length); 
480 exit:
481         if (buffer)
482                 OBD_FREE(buffer, PAGE_SIZE);        
483         
484         RETURN(rc);
485 }
486
487 static int kml_unlink(struct inode * inode, void *arg, struct kml_priv * priv) 
488 {
489         struct hook_unlink_msg * msg = arg;
490         char   *buffer = NULL;
491         int  length = 0, rc = 0;
492         ENTRY;
493          
494         OBD_ALLOC(buffer, PAGE_SIZE);
495         if (!buffer)
496                 GOTO(exit, rc = -ENOMEM);        
497       
498         rc = priv->pack_fn(REINT_UNLINK, buffer, msg->dentry, inode, 
499                            &msg->mode, NULL);
500         if (rc <= 0)
501                 GOTO(exit, rc);
502         
503         length += rc;         
504         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void*)buffer, length); 
505 exit:
506         if (buffer)
507                 OBD_FREE(buffer, PAGE_SIZE);        
508         
509         RETURN(rc);
510 }
511
512 static int kml_symlink(struct inode *inode, void *arg, struct kml_priv *priv) 
513 {
514         struct smfs_super_info *smb = S2SMI(inode->i_sb);
515         struct hook_symlink_msg *msg = arg;
516         int rc = 0, length = 0;
517         char *buffer = NULL;
518         ENTRY;
519         
520         OBD_ALLOC(buffer, PAGE_SIZE);
521         if (!buffer)
522                 GOTO(exit, rc = -ENOMEM);        
523
524         rc = priv->pack_fn(REINT_CREATE, buffer, msg->dentry, inode,
525                            msg->symname, &msg->tgt_len);
526         if (rc <= 0)
527                 GOTO(exit, rc);
528         
529         length += rc;
530         rc = smfs_llog_add_rec(smb, (void*)buffer, length); 
531 exit:
532         if (buffer)
533                 OBD_FREE(buffer, PAGE_SIZE);        
534         
535         RETURN(rc);
536 }
537
538 static int kml_rename(struct inode *inode, void *arg, struct kml_priv *priv) 
539 {
540         struct hook_rename_msg *msg = arg;
541         int rc = 0, length = 0;
542         char *buffer = NULL;
543         ENTRY;
544         
545         OBD_ALLOC(buffer, PAGE_SIZE);
546         if (!buffer)
547                 GOTO(exit, rc = -ENOMEM);
548         
549         rc = priv->pack_fn(REINT_RENAME, buffer, msg->dentry, inode, 
550                            msg->new_dir, msg->new_dentry);
551         if (rc <= 0) 
552                 GOTO(exit, rc);
553         length += rc;
554         
555         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void*)buffer, length); 
556 exit:
557         if (buffer)
558                 OBD_FREE(buffer, PAGE_SIZE);
559         RETURN(rc);
560 }
561
562 static int kml_setattr(struct inode *inode, void *arg, struct kml_priv *priv) 
563 {
564         struct hook_setattr_msg *msg = arg;
565         int rc = 0, length = 0;
566         char *buffer = NULL;
567         ENTRY;
568
569         OBD_ALLOC(buffer, PAGE_SIZE);
570         if (!buffer)
571                 GOTO(exit, rc = -ENOMEM);        
572
573         rc = priv->pack_fn(REINT_SETATTR, buffer, msg->dentry, inode, 
574                            msg->attr, NULL);
575         if (rc <= 0) 
576                 GOTO(exit, rc);
577         
578         length += rc;
579         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void*)buffer, length); 
580         /*
581         if (!rc) {
582                 if (attr && attr->ia_valid & ATTR_SIZE) {
583                         smfs_remove_extents_ea(inode, attr->ia_size,
584                                                0xffffffff);                                
585                         if (attr->ia_size == 0)
586                                 smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
587                         else
588                                 smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
589                 }
590         }
591         */
592 exit:
593         if (buffer)
594                 OBD_FREE(buffer, PAGE_SIZE);        
595         RETURN(rc);
596 }
597 /*
598 static int kml_write(struct inode * inode, void *arg, struct kml_priv * priv) 
599 {
600         struct hook_write_msg * msg = arg;
601         //return smfs_post_rec_write(inode, msg->dentry, &msg->count, &msg->pos);
602         struct smfs_super_info *sinfo;
603         char   *buffer = NULL, *pbuf;
604         int rc = 0, length = 0, buf_len = 0;
605         ENTRY;
606         
607         if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) && 
608             !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) {
609                 sinfo = S2SMI(dentry->d_inode->i_sb);
610                 if (!sinfo)
611                         RETURN(-EINVAL);
612                 
613                 OBD_ALLOC(buffer, PAGE_SIZE);
614                 if (!buffer)
615                         GOTO(exit, rc = -ENOMEM);        
616                 
617                 buf_len = PAGE_SIZE;
618                 KML_BUF_REC_INIT(buffer, pbuf, buf_len);        
619                 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
620                 
621                 if (rc < 0)
622                         GOTO(exit, rc);
623                 pbuf += rc;
624                 memcpy(buffer, &rc, sizeof(int));        
625                 length = rc + sizeof(int);
626                         
627                 rc = smfs_pack_rec(pbuf, dentry, dir, 
628                                    data1, data2, REINT_WRITE);
629                 if (rc <= 0) 
630                         GOTO(exit, rc);
631                 else
632                         length += rc;
633  
634                 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
635                 if (rc)
636                         GOTO(exit, rc);
637                 rc = smfs_init_extents_ea(dentry->d_inode);
638                 if (rc)
639                         GOTO(exit, rc);
640         } 
641         if (dentry->d_inode->i_size == 0) {
642                 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);        
643         } else {
644                 //insert extent EA
645                 loff_t off = *((loff_t*)data1);        
646                 size_t count = *((size_t*)data2);
647                 
648                 rc = smfs_insert_extents_ea(dentry->d_inode, off, count);        
649                 if (rc < 0)  
650                         GOTO(exit, rc);        
651                 if (all_blocks_present_ea(dentry->d_inode)){
652                         smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);        
653                         smfs_remove_all_extents_ea(dentry->d_inode);
654                 } else {
655                         smfs_set_dirty_flags(dentry->d_inode, SMFS_DIRTY_WRITE);        
656                 }
657         }
658 exit:
659         if (buffer)
660                 OBD_FREE(buffer, PAGE_SIZE);
661         RETURN(rc);
662 }
663 */
664
665 typedef int (*post_kml_op)(struct inode * inode, void *msg, struct kml_priv * priv);
666 static post_kml_op smfs_kml_post[HOOK_MAX] = {
667         [HOOK_CREATE]  kml_create,
668         [HOOK_LOOKUP]  NULL,
669         [HOOK_LINK]    kml_link,
670         [HOOK_UNLINK]  kml_unlink,
671         [HOOK_SYMLINK] kml_symlink,
672         [HOOK_MKDIR]   kml_create,
673         [HOOK_RMDIR]   kml_unlink,
674         [HOOK_MKNOD]   kml_create,
675         [HOOK_RENAME]  kml_rename,
676         [HOOK_SETATTR] kml_setattr,
677         [HOOK_WRITE]   NULL,
678         [HOOK_READDIR] NULL,
679 };
680
681 static int smfs_kml_post_op(int code, struct inode * inode,
682                             void * msg, int ret, void * priv)
683 {
684         int rc = 0;
685         
686         ENTRY;
687                 
688         //KML don't handle failed ops
689         if (ret)
690                 RETURN(0);
691         
692         if (smfs_kml_post[code]) {
693                 CDEBUG(D_INODE,"KML: inode %lu, code: %u\n", inode->i_ino, code);
694                 rc = smfs_kml_post[code](inode, msg, priv);
695         }
696                 
697         RETURN(rc);
698 }
699
700 /* Helpers */
701 static int smfs_exit_kml(struct super_block *sb, void * arg, struct kml_priv * priv)
702 {
703         struct smfs_plugin * plg = NULL;
704         ENTRY;
705
706         plg = smfs_deregister_plugin(sb, SMFS_PLG_KML);
707         if (plg)
708                 OBD_FREE(plg, sizeof(*plg));
709         else
710                 CERROR("Cannot find KLM plugin while unregistering\n");
711         
712         if (priv)
713                 OBD_FREE(priv, sizeof(*priv));
714         
715         EXIT;
716         return 0;
717 }
718
719 static int smfs_trans_kml (struct super_block *sb, void *arg,
720                            struct kml_priv * priv)
721 {
722         int size;
723         
724         //TODO: pass fs opcode and see if kml can participate or not
725         //one record in log per operation
726         size = 1;
727         
728         return size;
729 }
730
731 extern int mds_rec_pack(int, char*, struct dentry*, struct inode*, void*, void*);
732
733 static int smfs_start_kml(struct super_block *sb, void *arg,
734                           struct kml_priv * kml_p)
735 {
736         int rc = 0;
737         struct smfs_super_info * smb = S2SMI(sb);
738         struct llog_ctxt **ctxt = &smb->smsi_kml_log;
739         struct obd_device *obd = arg;
740
741         ENTRY;
742         //is plugin already activated
743         if (SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
744                 RETURN(0);
745         
746         if (obd && obd->obd_type && obd->obd_type->typ_name) {
747                 if (strcmp(obd->obd_type->typ_name, "mds"))
748                         RETURN(0);                
749         }
750         
751         kml_p->pack_fn = mds_rec_pack;
752         
753         //this will do OBD_ALLOC() for ctxt
754         rc = llog_catalog_setup(ctxt, KML_LOG_NAME, smb->smsi_exp,
755                                 smb->smsi_ctxt, smb->sm_fsfilt,
756                                 smb->smsi_logs_dir,
757                                 smb->smsi_objects_dir);
758         
759         if (rc) {
760                 CERROR("Failed to initialize kml log list catalog %d\n", rc);
761                 RETURN(rc);
762         }
763         
764         (*ctxt)->llog_proc_cb = NULL;//smfs_llog_process_rec_cb;
765
766         SMFS_SET(smb->plg_flags, SMFS_PLG_KML);
767
768         RETURN(0);
769 }
770
771 int smfs_stop_kml(struct super_block *sb, void *arg,
772                   struct kml_priv * kml_p)
773 {
774         struct smfs_super_info * smb = S2SMI(sb);
775         struct llog_ctxt *ctxt = smb->smsi_kml_log;
776         ENTRY;
777
778         if (!SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
779                 RETURN(0);
780
781         SMFS_CLEAR(smb->plg_flags, SMFS_PLG_KML);
782
783         llog_catalog_cleanup(ctxt);
784         OBD_FREE(ctxt, sizeof(*ctxt));
785         
786         RETURN(0);
787 }
788
789 typedef int (*kml_helper)(struct super_block * sb, void *msg, struct kml_priv *);
790 static kml_helper smfs_kml_helpers[PLG_HELPER_MAX] = {
791         [PLG_EXIT]       smfs_exit_kml,
792         [PLG_START]      smfs_start_kml,
793         [PLG_STOP]       smfs_stop_kml,
794         [PLG_TRANS_SIZE] smfs_trans_kml,
795         [PLG_TEST_INODE] NULL,
796         [PLG_SET_INODE]  NULL,
797 };
798
799 static int smfs_kml_help_op(int code, struct super_block * sb,
800                             void * arg, void * priv)
801 {
802         int rc = 0;
803         
804         if (smfs_kml_helpers[code])
805                 rc = smfs_kml_helpers[code](sb, arg, (struct kml_priv *) priv);
806         return rc;
807 }
808
809 int smfs_init_kml(struct super_block *sb)
810 {
811         int rc = 0;
812         struct kml_priv * priv = NULL;
813         struct smfs_plugin * plg = NULL;
814         ENTRY;
815         
816         OBD_ALLOC(plg, sizeof(*plg));
817         if (!plg) {
818                 rc = -ENOMEM;
819                 goto exit;
820         }
821         
822         plg->plg_type = SMFS_PLG_KML;
823         plg->plg_pre_op = NULL;
824         plg->plg_post_op = &smfs_kml_post_op;
825         plg->plg_helper = &smfs_kml_help_op;
826                 
827         OBD_ALLOC(priv, sizeof(*priv));
828         if (!priv) {
829                 rc = -ENOMEM;
830                 goto exit;
831         }
832
833         plg->plg_private = priv;
834
835         rc = smfs_register_plugin(sb, plg);
836         if (!rc) 
837                 RETURN(0);
838 exit: 
839         if (priv)
840                 OBD_FREE(priv, sizeof(*priv));
841         
842         if (plg)
843                 OBD_FREE(plg, sizeof(*plg));
844
845         RETURN(rc);
846 }
847
848