Whamcloud - gitweb
- remove non-needed CERROR
[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 #define KML_BUF_REC_INIT(buffer, pbuf, len)     \
43 do {                                            \
44         pbuf = buffer + sizeof(int);            \
45         len -= sizeof(int);                     \
46 } while (0)
47         
48 #define KML_BUF_REC_END(buffer, length, pbuf)   \
49 do {                                            \
50         int len = length;                       \
51         memcpy(buffer, &len, sizeof(len));      \
52         length += sizeof(int);                  \
53         pbuf = buffer + length;                 \
54 } while (0)
55
56 static int smfs_llog_process_rec_cb(struct llog_handle *handle,
57                                     struct llog_rec_hdr *rec, void *data)
58 {
59         char   *rec_buf ;
60         struct smfs_proc_args *args = (struct smfs_proc_args *)data;
61         struct lvfs_run_ctxt saved;
62         int    rc = 0;
63
64         if (!(le32_to_cpu(handle->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) {
65                 CERROR("log is not plain\n");
66                 RETURN(-EINVAL);
67         }
68
69         if (le32_to_cpu(rec->lrh_type) == LLOG_GEN_REC) {
70                 struct llog_cookie cookie;
71
72                 cookie.lgc_lgl = handle->lgh_id;
73                 cookie.lgc_index = le32_to_cpu(rec->lrh_index);
74
75                 llog_cancel(handle->lgh_ctxt, 1, &cookie, 0, NULL);
76                 RETURN(LLOG_PROC_BREAK);
77         }
78
79         if (le32_to_cpu(rec->lrh_type) != SMFS_UPDATE_REC)
80                 RETURN(-EINVAL);
81
82         rec_buf = (char*) (rec + 1);
83
84         if (!S2SMI(args->sr_sb)->smsi_ctxt)
85                 GOTO(exit, rc = -ENODEV);
86
87         push_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
88 #if 0
89         /*FIXME later should first unpack the rec,
90          * then call lvfs_reint or lvfs_undo
91          * kml rec format has changed lvfs_reint lvfs_undo should
92          * be rewrite FIXME later*/
93         if (SMFS_DO_REINT_REC(args->sr_flags))
94                 rc = lvfs_reint(args->sr_sb, rec_buf);
95         else
96                 rc = lvfs_undo(args->sr_sb, rec_buf);
97 #endif
98         if (!rc && !SMFS_DO_REC_ALL(args->sr_flags)) {
99                 args->sr_count --;
100                 if (args->sr_count == 0)
101                         rc = LLOG_PROC_BREAK;
102         }
103         pop_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
104 exit:
105         RETURN(rc);
106 }
107
108 #if 0
109 /* not used curently */
110 static smfs_pack_rec_func smfs_get_rec_pack_type(struct super_block *sb)
111 {
112         int idx = 0;
113         struct smfs_super_info *smsi = S2SMI(sb);
114
115         idx = GET_REC_PACK_TYPE_INDEX(smsi->smsi_flags);
116         return smsi->smsi_pack_rec[idx];
117 }
118 #endif
119
120 static inline void
121 copy_inode_attr(struct iattr *iattr, struct inode *inode)
122 {
123         iattr->ia_mode = inode->i_mode;
124         iattr->ia_uid  = inode->i_uid;
125         iattr->ia_gid  = inode->i_gid;
126         iattr->ia_atime = inode->i_atime;
127         iattr->ia_ctime = inode->i_ctime;
128         iattr->ia_mtime = inode->i_mtime;
129         iattr->ia_size = inode->i_size;
130 }
131
132 #if 0
133 static inline int unpack_rec_data(char **p_buffer, int *size,
134                                   char *in_data, char *args_data)
135 {
136         int args_len = 0;
137         int rc = 0;
138         ENTRY;
139
140         if (args_data)
141                 args_len = strlen(args_data);
142
143         *size = *((int*)(in_data));
144         rc = *size + sizeof(int);
145
146         OBD_ALLOC(*p_buffer, *size + args_len + 1);
147         if (!*p_buffer)
148                 RETURN(-ENOMEM);
149
150         /* first copy reint dir. */
151         if (args_data)
152                 memcpy(*p_buffer, args_data, args_len);
153
154         /* then copy the node name. */
155         memcpy(*p_buffer + args_len,
156                       (in_data + sizeof(int)), *size);
157
158         *size += args_len;
159
160         RETURN(rc);
161 }
162 #endif
163
164 int smfs_rec_unpack(struct smfs_proc_args *args, char *record, 
165                     char **pbuf, int *opcode)
166 {
167         //int offset = *(int *)(record);
168         //char *tmp = record + offset + sizeof(int);
169
170         *opcode = *(int *)record;
171         *pbuf = record + sizeof(*opcode);
172         return 0;
173 }
174 EXPORT_SYMBOL(smfs_rec_unpack); /* cmobd/cm_reint.c */
175
176 int smfs_write_extents(struct inode *dir, struct dentry *dentry,
177                        unsigned long from, unsigned long num)
178 {
179         return 0;//smfs_post_rec_write(dir, dentry, &from, &num);
180 }
181 #if 0
182 int smfs_rec_precreate(struct dentry *dentry, int *num, struct obdo *oa)
183 {
184        return smfs_post_rec_create(dentry->d_inode, dentry, num, oa);
185 }
186
187 int smfs_process_rec(struct super_block *sb,
188                      int count, char *dir, int flags)
189 {
190         struct llog_ctxt *ctxt;
191         struct llog_handle *loghandle;
192         struct smfs_proc_args args;
193         int rc = 0;
194         ENTRY;
195
196         if (!SMFS_INIT_REC(S2SMI(sb))) {
197                 CWARN("Did not start up rec server \n");
198                 RETURN(rc);
199         }
200
201         memset(&args, 0, sizeof(struct smfs_proc_args));
202         args.sr_sb = sb;
203         args.sr_count = count;
204         args.sr_data = dir;
205         args.sr_flags = flags ;
206         ctxt = S2SMI(sb)->smsi_kml_log;
207         loghandle = ctxt->loc_handle;
208
209         if (count == 0) {
210                 if (SMFS_DO_REINT_REC(flags)) {
211                         struct llog_gen_rec *lgr;
212
213                         /* for reint rec, we need insert a gen rec to identify
214                          * the end of the rec.*/
215                         OBD_ALLOC(lgr, sizeof(*lgr));
216                         if (!lgr)
217                                 RETURN(-ENOMEM);
218                         lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len = sizeof(*lgr);
219                         lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
220                         lgr->lgr_gen = ctxt->loc_gen;
221                         rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1,
222                                       NULL, NULL, NULL);
223                         OBD_FREE(lgr, sizeof(*lgr));
224                         if (rc != 1)
225                                 RETURN(rc);
226                 }
227         } else {
228                 SET_REC_COUNT_FLAGS(args.sr_flags, SMFS_REC_ALL);
229         }
230         if (loghandle) {
231                 if (SMFS_DO_REINT_REC(flags))
232                         rc = llog_cat_process(loghandle, ctxt->llog_proc_cb,
233                                               (void *)&args);
234                 else
235                         rc = llog_cat_reverse_process(loghandle,
236                                                       ctxt->llog_proc_cb,
237                                                       (void *)&args);
238                 if (rc == LLOG_PROC_BREAK)
239                         rc = 0;
240         }
241         RETURN(rc);
242 }
243 #endif
244
245 #if 0
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         ENTRY;
704
705         smfs_deregister_plugin(sb, SMFS_PLG_KML);
706         OBD_FREE(priv, sizeof(*priv));
707         
708         EXIT;
709         return 0;
710 }
711
712 static int smfs_trans_kml (struct super_block *sb, void *arg,
713                            struct kml_priv * priv)
714 {
715         int size;
716         
717         //TODO: pass fs opcode and see if kml can participate or not
718         //one record in log per operation
719         size = 1;
720         
721         return size;
722 }
723
724 extern int mds_rec_pack(int, char*, struct dentry*, struct inode*, void*, void*);
725
726 static int smfs_start_kml(struct super_block *sb, void *arg,
727                           struct kml_priv * kml_p)
728 {
729         int rc = 0;
730         struct smfs_super_info * smb = S2SMI(sb);
731         struct llog_ctxt **ctxt = &smb->smsi_kml_log;
732         struct obd_device *obd = arg;
733
734         ENTRY;
735         //is plugin already activated
736         if (SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
737                 RETURN(0);
738         
739         if (obd && obd->obd_type && obd->obd_type->typ_name) {
740                 if (strcmp(obd->obd_type->typ_name, "mds"))
741                         RETURN(0);                
742         }
743         
744         kml_p->pack_fn = mds_rec_pack;
745         
746         //this will do OBD_ALLOC() for ctxt
747         rc = llog_catalog_setup(ctxt, KML_LOG_NAME, smb->smsi_exp,
748                                 smb->smsi_ctxt, smb->sm_fsfilt,
749                                 smb->smsi_logs_dir,
750                                 smb->smsi_objects_dir);
751         
752         if (rc) {
753                 CERROR("Failed to initialize kml log list catalog %d\n", rc);
754                 RETURN(rc);
755         }
756         
757         (*ctxt)->llog_proc_cb = smfs_llog_process_rec_cb;
758
759         SMFS_SET(smb->plg_flags, SMFS_PLG_KML);
760
761         RETURN(0);
762 }
763
764 int smfs_stop_kml(struct super_block *sb, void *arg,
765                   struct kml_priv * kml_p)
766 {
767         struct smfs_super_info * smb = S2SMI(sb);
768         struct llog_ctxt *ctxt = smb->smsi_kml_log;
769         ENTRY;
770
771         if (!SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
772                 RETURN(0);
773
774         SMFS_CLEAR(smb->plg_flags, SMFS_PLG_KML);
775
776         llog_catalog_cleanup(ctxt);
777         OBD_FREE(ctxt, sizeof(*ctxt));
778         
779         RETURN(0);
780 }
781
782 typedef int (*kml_helper)(struct super_block * sb, void *msg, struct kml_priv *);
783 static kml_helper smfs_kml_helpers[PLG_HELPER_MAX] = {
784         [PLG_EXIT]       smfs_exit_kml,
785         [PLG_START]      smfs_start_kml,
786         [PLG_STOP]       smfs_stop_kml,
787         [PLG_TRANS_SIZE] smfs_trans_kml,
788         [PLG_TEST_INODE] NULL,
789         [PLG_SET_INODE]  NULL,
790 };
791
792 static int smfs_kml_help_op(int code, struct super_block * sb,
793                             void * arg, void * priv)
794 {
795         int rc = 0;
796         
797         if (smfs_kml_helpers[code])
798                 rc = smfs_kml_helpers[code](sb, arg, (struct kml_priv *) priv);
799         return rc;
800 }
801
802 int smfs_init_kml(struct super_block *sb)
803 {
804         int rc = 0;
805         struct kml_priv * priv = NULL;
806         struct smfs_plugin plg = {
807                 .plg_type = SMFS_PLG_KML,
808                 .plg_pre_op = NULL,
809                 .plg_post_op = &smfs_kml_post_op,
810                 .plg_helper = &smfs_kml_help_op,
811                 .plg_private = NULL,
812         };
813         
814         ENTRY;
815
816         OBD_ALLOC(priv, sizeof(*priv));
817         if (!priv) {
818                 RETURN(-ENOMEM);
819         }
820
821         plg.plg_private = priv;
822         /*
823         rc = ost_rec_pack_init(smb);
824         if (rc)
825                 return rc;
826         
827         rc = mds_rec_pack_init(smb);
828         if (rc)
829                 return rc;
830         */
831         rc = smfs_register_plugin(sb, &plg);
832         
833         RETURN(rc);
834 }
835
836