Whamcloud - gitweb
- landed b_hd_mdref (mostly WB cache fixes)
[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
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         //smfs_post_rec_write(dir, dentry, &from, &num);
180         return 0;
181 }
182 #if 0
183 int smfs_rec_precreate(struct dentry *dentry, int *num, struct obdo *oa)
184 {
185        return smfs_post_rec_create(dentry->d_inode, dentry, num, oa);
186 }
187
188 int smfs_process_rec(struct super_block *sb,
189                      int count, char *dir, int flags)
190 {
191         struct llog_ctxt *ctxt;
192         struct llog_handle *loghandle;
193         struct smfs_proc_args args;
194         int rc = 0;
195         ENTRY;
196
197         if (!SMFS_INIT_REC(S2SMI(sb))) {
198                 CWARN("Did not start up rec server \n");
199                 RETURN(rc);
200         }
201
202         memset(&args, 0, sizeof(struct smfs_proc_args));
203         args.sr_sb = sb;
204         args.sr_count = count;
205         args.sr_data = dir;
206         args.sr_flags = flags ;
207         ctxt = S2SMI(sb)->smsi_kml_log;
208         loghandle = ctxt->loc_handle;
209
210         if (count == 0) {
211                 if (SMFS_DO_REINT_REC(flags)) {
212                         struct llog_gen_rec *lgr;
213
214                         /* for reint rec, we need insert a gen rec to identify
215                          * the end of the rec.*/
216                         OBD_ALLOC(lgr, sizeof(*lgr));
217                         if (!lgr)
218                                 RETURN(-ENOMEM);
219                         lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len = sizeof(*lgr);
220                         lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
221                         lgr->lgr_gen = ctxt->loc_gen;
222                         rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1,
223                                       NULL, NULL, NULL);
224                         OBD_FREE(lgr, sizeof(*lgr));
225                         if (rc != 1)
226                                 RETURN(rc);
227                 }
228         } else {
229                 SET_REC_COUNT_FLAGS(args.sr_flags, SMFS_REC_ALL);
230         }
231         if (loghandle) {
232                 if (SMFS_DO_REINT_REC(flags))
233                         rc = llog_cat_process(loghandle, ctxt->llog_proc_cb,
234                                               (void *)&args);
235                 else
236                         rc = llog_cat_reverse_process(loghandle,
237                                                       ctxt->llog_proc_cb,
238                                                       (void *)&args);
239                 if (rc == LLOG_PROC_BREAK)
240                         rc = 0;
241         }
242         RETURN(rc);
243 }
244
245 /* smfs_path is gotten from intermezzo */
246 static char *smfs_path(struct dentry *dentry, struct dentry *root, char *buffer,
247                        int buflen)
248 {
249         char * end = buffer + buflen;
250         char * name = buffer;
251         char * buf_end = buffer + buflen;
252         char * retval;
253
254         *--end = '\0';
255         buflen--;
256         /* Get '/' right */
257         retval = end-1;
258         *retval = '/';
259
260         for (;;) {
261                 struct dentry * parent;
262                 int namelen;
263
264                 if (dentry == root)
265                         break;
266                 parent = dentry->d_parent;
267                 if (dentry == parent)
268                         break;
269                 namelen = dentry->d_name.len;
270                 buflen -= namelen + 1;
271                 if (buflen < 0)
272                         break;
273                 end -= namelen;
274                 memcpy(end, dentry->d_name.name, namelen);
275                 *--end = '/';
276                 retval = end;
277                 dentry = parent;
278         }
279         
280         while (end != buf_end) 
281                 *name++ = *end++;
282         *name = '\0'; 
283         return retval;
284 }
285
286 static int smfs_log_path(struct super_block *sb, 
287                          struct dentry *dentry, 
288                          char   *buffer,
289                          int    buffer_len)
290 {
291         struct dentry *root=sb->s_root;
292         char *p_name = buffer + sizeof(int);
293         char *name = NULL;
294         int namelen = 0;
295         ENTRY;
296
297         if (dentry) {
298                 name = smfs_path(dentry, root, p_name, buffer_len - sizeof(int));
299                 namelen = cpu_to_le32(strlen(p_name));
300                 memcpy(buffer, &namelen, sizeof(int));        
301         }
302         namelen += sizeof(int);
303         RETURN(namelen);
304 }
305
306 static int smfs_pack_rec (char *buffer, struct dentry *dentry, 
307                           struct inode *dir, void *data1, 
308                           void *data2, int op)
309
310         smfs_pack_rec_func pack_func;        
311
312         pack_func = smfs_get_rec_pack_type(dir->i_sb);
313         if (!pack_func)
314                 return 0;
315         return pack_func(buffer, dentry, dir, data1, data2, op);
316 }
317
318 static int smfs_insert_extents_ea(struct inode *inode, size_t from, loff_t num)
319 {
320         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
321         int rc = 0;
322         ENTRY;
323         
324         if (SMFS_INODE_OVER_WRITE(inode))
325                 RETURN(rc);
326         
327         rc = fsfilt->fs_insert_extents_ea(inode, OFF2BLKS(from, inode), 
328                                           SIZE2BLKS(num, inode));        
329         RETURN(rc);
330 }
331
332 static int smfs_remove_extents_ea(struct inode *inode, size_t from, loff_t num)
333 {
334         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
335         int rc = 0;
336         ENTRY;
337         
338         rc = fsfilt->fs_remove_extents_ea(inode, OFF2BLKS(from, inode), 
339                                           SIZE2BLKS(num, inode));        
340         
341         RETURN(rc);
342 }
343
344 static int smfs_remove_all_extents_ea(struct inode *inode)
345 {
346         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
347         int rc = 0;
348         ENTRY;
349         
350         rc = fsfilt->fs_remove_extents_ea(inode, 0, 0xffffffff);        
351         RETURN(rc);
352 }
353 static int  smfs_init_extents_ea(struct inode *inode)
354 {
355         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
356         int rc = 0;
357         ENTRY;
358         
359         rc = fsfilt->fs_init_extents_ea(inode);        
360         
361         RETURN(rc);
362 }
363 static int smfs_set_dirty_flags(struct inode *inode, int flags)
364 {
365         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
366         void   *handle;
367         int    rc = 0;
368         ENTRY;
369
370         if (SMFS_INODE_OVER_WRITE(inode))
371                 RETURN(rc);
372         /*FIXME later, the blocks needed in journal here will be recalculated*/
373          handle = smfs_trans_start(inode, FSFILT_OP_SETATTR);
374         if (IS_ERR(handle)) {
375                 CERROR("smfs_set_dirty_flag:no space for transaction\n");
376                 RETURN(-ENOSPC);
377         }
378         if ((!SMFS_INODE_DIRTY_WRITE(inode) && (!SMFS_INODE_OVER_WRITE(inode))) || 
379              ((flags == SMFS_OVER_WRITE) && (SMFS_INODE_DIRTY_WRITE(inode)))) {        
380                 rc = fsfilt->fs_set_xattr(inode, handle, REINT_EXTENTS_FLAGS,
381                                             &flags, sizeof(int));
382                 if (rc)
383                         GOTO(out, rc);
384         }
385         if (flags == SMFS_OVER_WRITE)
386                 SMFS_SET_INODE_OVER_WRITE(inode);
387         else
388                 SMFS_SET_INODE_DIRTY_WRITE(inode);
389 out:
390         smfs_trans_commit(inode, handle, 0);
391         RETURN(rc);
392 }
393
394 static int all_blocks_present_ea(struct inode *inode)
395 {
396         int rc = 0;
397         ENTRY;
398         RETURN(rc);        
399 }
400 #endif
401
402 /* new plugin API */
403 #if 0
404 static int kml_pack_path (char **buf, struct dentry * dentry)
405 {
406         char *pbuf;
407         int length = 0, rc = 0;
408         
409         OBD_ALLOC(*buf, PAGE_SIZE);
410         if (*buf == NULL)
411                 return -ENOMEM;        
412
413         length = PAGE_SIZE;
414         KML_BUF_REC_INIT(*buf, pbuf, length);
415         rc = smfs_log_path(dentry->d_sb, dentry, pbuf, length);
416         if (rc < 0) {
417                 return rc;
418         }
419         
420         length = rc;
421         KML_BUF_REC_END(*buf, length, pbuf);  
422         
423         return length;
424 }
425 #endif
426
427 static int kml_create(struct inode *inode, void *arg,
428                       struct kml_priv *priv) 
429 {
430         struct hook_msg * msg = arg;
431         //return smfs_post_rec_create(inode, msg->dentry, NULL, NULL);
432         struct smfs_super_info *smb = S2SMI(inode->i_sb);
433         char   *buffer = NULL;
434         int rc = 0, length = 0;
435         ENTRY;
436         
437         OBD_ALLOC(buffer, PAGE_SIZE);
438         if (buffer == NULL)
439                 return -ENOMEM;    
440         
441         /*
442         rc = kml_pack_path(&buffer, msg->dentry);
443         if (rc < 0)
444                 goto exit;
445         
446         length = rc;
447         pbuf = buffer + length;
448         */        
449         rc = priv->pack_fn(REINT_CREATE, buffer, msg->dentry, inode,
450                            NULL, NULL);
451         if (rc <= 0)
452                 GOTO(exit, rc);
453         
454         length += rc;
455         rc = smfs_llog_add_rec(smb, (void*)buffer, length); 
456 exit:
457         if (buffer)
458                 OBD_FREE(buffer, PAGE_SIZE);        
459         
460         RETURN(rc);
461 }
462
463 static int kml_link(struct inode *inode, void *arg, struct kml_priv *priv) 
464 {
465         struct hook_link_msg *msg = arg;
466         int rc = 0, length = 0;
467         char *buffer = NULL;
468         ENTRY;
469         
470         OBD_ALLOC(buffer, PAGE_SIZE);
471         if (!buffer)
472                 GOTO(exit, rc = -ENOMEM);
473         
474         rc = priv->pack_fn(REINT_LINK, buffer, msg->dentry, inode, 
475                            msg->dentry, msg->new_dentry);
476         if (rc <= 0)
477                 GOTO(exit, rc);
478         
479         length += rc;
480         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void *)buffer, length); 
481 exit:
482         if (buffer)
483                 OBD_FREE(buffer, PAGE_SIZE);        
484         
485         RETURN(rc);
486 }
487
488 static int kml_unlink(struct inode * inode, void *arg, struct kml_priv * priv) 
489 {
490         struct hook_unlink_msg * msg = arg;
491         char   *buffer = NULL;
492         int  length = 0, rc = 0;
493         ENTRY;
494          
495         OBD_ALLOC(buffer, PAGE_SIZE);
496         if (!buffer)
497                 GOTO(exit, rc = -ENOMEM);        
498       
499         rc = priv->pack_fn(REINT_UNLINK, buffer, msg->dentry, inode, 
500                            &msg->mode, NULL);
501         if (rc <= 0)
502                 GOTO(exit, rc);
503         
504         length += rc;         
505         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void*)buffer, length); 
506 exit:
507         if (buffer)
508                 OBD_FREE(buffer, PAGE_SIZE);        
509         
510         RETURN(rc);
511 }
512
513 static int kml_symlink(struct inode *inode, void *arg, struct kml_priv *priv) 
514 {
515         struct smfs_super_info *smb = S2SMI(inode->i_sb);
516         struct hook_symlink_msg *msg = arg;
517         int rc = 0, length = 0;
518         char *buffer = NULL;
519         ENTRY;
520         
521         OBD_ALLOC(buffer, PAGE_SIZE);
522         if (!buffer)
523                 GOTO(exit, rc = -ENOMEM);        
524
525         rc = priv->pack_fn(REINT_CREATE, buffer, msg->dentry, inode,
526                            msg->symname, &msg->tgt_len);
527         if (rc <= 0)
528                 GOTO(exit, rc);
529         
530         length += rc;
531         rc = smfs_llog_add_rec(smb, (void*)buffer, length); 
532 exit:
533         if (buffer)
534                 OBD_FREE(buffer, PAGE_SIZE);        
535         
536         RETURN(rc);
537 }
538
539 static int kml_rename(struct inode *inode, void *arg, struct kml_priv *priv) 
540 {
541         struct hook_rename_msg *msg = arg;
542         int rc = 0, length = 0;
543         char *buffer = NULL;
544         ENTRY;
545         
546         OBD_ALLOC(buffer, PAGE_SIZE);
547         if (!buffer)
548                 GOTO(exit, rc = -ENOMEM);
549         
550         rc = priv->pack_fn(REINT_RENAME, buffer, msg->dentry, inode, 
551                            msg->new_dir, msg->new_dentry);
552         if (rc <= 0) 
553                 GOTO(exit, rc);
554         length += rc;
555         
556         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void*)buffer, length); 
557 exit:
558         if (buffer)
559                 OBD_FREE(buffer, PAGE_SIZE);
560         RETURN(rc);
561 }
562
563 static int kml_setattr(struct inode *inode, void *arg, struct kml_priv *priv) 
564 {
565         struct hook_attr_msg *msg = arg;
566         int rc = 0, length = 0;
567         char *buffer = NULL;
568         ENTRY;
569
570         OBD_ALLOC(buffer, PAGE_SIZE);
571         if (!buffer)
572                 GOTO(exit, rc = -ENOMEM);        
573
574         rc = priv->pack_fn(REINT_SETATTR, buffer, msg->dentry, inode, 
575                            msg->attr, NULL);
576         if (rc <= 0) 
577                 GOTO(exit, rc);
578         
579         length += rc;
580         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void *)buffer, length); 
581         /*
582         if (!rc) {
583                 if (attr && attr->ia_valid & ATTR_SIZE) {
584                         smfs_remove_extents_ea(inode, attr->ia_size,
585                                                0xffffffff);                                
586                         if (attr->ia_size == 0)
587                                 smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
588                         else
589                                 smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
590                 }
591         }
592         */
593 exit:
594         if (buffer)
595                 OBD_FREE(buffer, PAGE_SIZE);        
596         RETURN(rc);
597 }
598
599 static int kml_setxattr(struct inode *inode, void *arg, struct kml_priv *priv) 
600 {
601         struct hook_xattr_msg *msg = arg;
602         struct kml_buffer kbuf;
603         int rc = 0, length = 0;
604         char *buffer = NULL;
605         ENTRY;
606
607         OBD_ALLOC(buffer, PAGE_SIZE);
608         if (!buffer)
609                 GOTO(exit, rc = -ENOMEM);        
610
611         kbuf.buf = msg->buffer;
612         kbuf.buf_size = msg->buffer_size;
613
614         rc = priv->pack_fn(REINT_SETXATTR, buffer, NULL, inode,
615                            msg->name, &kbuf);
616         if (rc <= 0) 
617                 GOTO(exit, rc);
618         
619         length += rc;
620         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void *)buffer, length); 
621         /*
622         if (!rc) {
623                 if (attr && attr->ia_valid & ATTR_SIZE) {
624                         smfs_remove_extents_ea(inode, attr->ia_size,
625                                                0xffffffff);                                
626                         if (attr->ia_size == 0)
627                                 smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
628                         else
629                                 smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
630                 }
631         }
632         */
633 exit:
634         if (buffer)
635                 OBD_FREE(buffer, PAGE_SIZE);        
636         RETURN(rc);
637 }
638
639 /*
640 static int kml_write(struct inode * inode, void *arg, struct kml_priv * priv) 
641 {
642         struct hook_write_msg * msg = arg;
643         //return smfs_post_rec_write(inode, msg->dentry, &msg->count, &msg->pos);
644         struct smfs_super_info *sinfo;
645         char   *buffer = NULL, *pbuf;
646         int rc = 0, length = 0, buf_len = 0;
647         ENTRY;
648         
649         if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) && 
650             !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) {
651                 sinfo = S2SMI(dentry->d_inode->i_sb);
652                 if (!sinfo)
653                         RETURN(-EINVAL);
654                 
655                 OBD_ALLOC(buffer, PAGE_SIZE);
656                 if (!buffer)
657                         GOTO(exit, rc = -ENOMEM);        
658                 
659                 buf_len = PAGE_SIZE;
660                 KML_BUF_REC_INIT(buffer, pbuf, buf_len);        
661                 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
662                 
663                 if (rc < 0)
664                         GOTO(exit, rc);
665                 pbuf += rc;
666                 memcpy(buffer, &rc, sizeof(int));        
667                 length = rc + sizeof(int);
668                         
669                 rc = smfs_pack_rec(pbuf, dentry, dir, 
670                                    data1, data2, REINT_WRITE);
671                 if (rc <= 0) 
672                         GOTO(exit, rc);
673                 else
674                         length += rc;
675  
676                 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
677                 if (rc)
678                         GOTO(exit, rc);
679                 rc = smfs_init_extents_ea(dentry->d_inode);
680                 if (rc)
681                         GOTO(exit, rc);
682         } 
683         if (dentry->d_inode->i_size == 0) {
684                 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);        
685         } else {
686                 //insert extent EA
687                 loff_t off = *((loff_t*)data1);        
688                 size_t count = *((size_t*)data2);
689                 
690                 rc = smfs_insert_extents_ea(dentry->d_inode, off, count);        
691                 if (rc < 0)  
692                         GOTO(exit, rc);        
693                 if (all_blocks_present_ea(dentry->d_inode)){
694                         smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);        
695                         smfs_remove_all_extents_ea(dentry->d_inode);
696                 } else {
697                         smfs_set_dirty_flags(dentry->d_inode, SMFS_DIRTY_WRITE);        
698                 }
699         }
700 exit:
701         if (buffer)
702                 OBD_FREE(buffer, PAGE_SIZE);
703         RETURN(rc);
704 }
705 */
706
707 typedef int (*post_kml_op)(struct inode *inode, void *msg,
708                            struct kml_priv *priv);
709
710 static post_kml_op smfs_kml_post[HOOK_MAX] = {
711         [HOOK_CREATE]  kml_create,
712         [HOOK_LOOKUP]  NULL,
713         [HOOK_LINK]    kml_link,
714         [HOOK_UNLINK]  kml_unlink,
715         [HOOK_SYMLINK] kml_symlink,
716         [HOOK_MKDIR]   kml_create,
717         [HOOK_RMDIR]   kml_unlink,
718         [HOOK_MKNOD]   kml_create,
719         [HOOK_RENAME]  kml_rename,
720         [HOOK_SETATTR] kml_setattr,
721         [HOOK_WRITE]   NULL,
722         [HOOK_READDIR] NULL,
723         [HOOK_F_SETXATTR] kml_setxattr,
724 };
725
726 static int smfs_kml_post_op(hook_op code, struct inode * inode,
727                             void * msg, int ret, void * priv)
728 {
729         int rc = 0;
730         
731         ENTRY;
732         
733         //check if inode has flag for KML               
734         if (!SMFS_IS(I2SMI(inode)->smi_flags, SMFS_PLG_KML))
735                 RETURN(0);
736  
737         //KML don't handle failed ops
738         if (ret)
739                 RETURN(0);
740
741         if (smfs_kml_post[code]) {
742                 CDEBUG(D_INODE,"KML: inode %lu, code: %u\n",
743                        inode->i_ino, code);
744                 rc = smfs_kml_post[code](inode, msg, priv);
745         }
746                 
747         RETURN(rc);
748 }
749
750 /* Helpers */
751 static int smfs_trans_kml (struct super_block *sb, void *arg,
752                            struct kml_priv * priv)
753 {
754         int size = 1;
755         ENTRY;
756         
757         /* FIXME-MIKE: pass fs opcode and see if kml can participate or not one
758          * record in log per operation size = 1 */
759
760         RETURN(size);
761 }
762
763 static int smfs_start_kml(struct super_block *sb, void *arg,
764                           struct kml_priv *kml_p)
765 {
766         struct smfs_super_info *smb = S2SMI(sb);
767         struct llog_ctxt **ctxt = &smb->smsi_kml_log;
768         struct obd_device *obd = arg;
769         int rc = 0;
770         ENTRY;
771
772         /* is plugin already activated */
773         if (SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
774                 RETURN(0);
775
776         if (obd && obd->obd_type && obd->obd_type->typ_name) {
777                 if (!strcmp(obd->obd_type->typ_name, OBD_MDS_DEVICENAME)) {
778                         kml_p->pack_fn = mds_rec_pack;
779                 } else if (!strcmp(obd->obd_type->typ_name, OBD_FILTER_DEVICENAME)) {
780                         kml_p->pack_fn = ost_rec_pack;
781                 } else {
782                         CWARN("unexpected device type: %s\n", obd->obd_type->typ_name);
783                 }
784         }
785
786         LASSERT(kml_p->pack_fn != NULL);
787
788         /* this will do OBD_ALLOC() for ctxt */
789         rc = llog_catalog_setup(ctxt, KML_LOG_NAME, smb->smsi_exp,
790                                 smb->smsi_ctxt, smb->sm_fsfilt,
791                                 smb->smsi_logs_dir, smb->smsi_objects_dir);
792         if (rc) {
793                 CERROR("failed to initialize kml log list catalog %d\n", rc);
794                 RETURN(rc);
795         }
796         
797         /* connect KML ctxt to obd */
798         if (obd && smb->smsi_kml_log) {
799                 smb->smsi_kml_log->loc_idx = LLOG_REINT_ORIG_CTXT;
800                 smb->smsi_kml_log->loc_obd = obd;
801                 smb->smsi_kml_log->loc_llogs = &obd->obd_llogs;
802                 obd->obd_llogs.llog_ctxt[LLOG_REINT_ORIG_CTXT] = smb->smsi_kml_log;
803         }
804
805         SMFS_SET(smb->plg_flags, SMFS_PLG_KML);
806         RETURN(0);
807 }
808
809 int smfs_stop_kml(struct super_block *sb, void *arg,
810                   struct kml_priv * kml_p)
811 {
812         struct smfs_super_info * smb = S2SMI(sb);
813         struct llog_ctxt *ctxt = smb->smsi_kml_log;
814         struct obd_device * obd = ctxt->loc_obd;
815         ENTRY;
816
817         if (!SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
818                 RETURN(0);
819
820         SMFS_CLEAR(smb->plg_flags, SMFS_PLG_KML);
821
822         llog_catalog_cleanup(ctxt);
823         obd->obd_llogs.llog_ctxt[LLOG_REINT_ORIG_CTXT] = NULL;
824         OBD_FREE(ctxt, sizeof(*ctxt));
825         
826         RETURN(0);
827 }
828
829 typedef int (*kml_helper)(struct super_block * sb, void *msg, struct kml_priv *);
830 static kml_helper smfs_kml_helpers[PLG_HELPER_MAX] = {
831         [PLG_START]      smfs_start_kml,
832         [PLG_STOP]       smfs_stop_kml,
833         [PLG_TRANS_SIZE] smfs_trans_kml,
834         [PLG_TEST_INODE] NULL,
835         [PLG_SET_INODE]  NULL,
836 };
837
838 static int smfs_kml_help_op(int code, struct super_block * sb,
839                             void * arg, void * priv)
840 {
841         int rc = 0;
842         
843         if (smfs_kml_helpers[code])
844                 rc = smfs_kml_helpers[code](sb, arg, (struct kml_priv *) priv);
845         return rc;
846 }
847
848 static int smfs_exit_kml(struct super_block *sb, void * arg)
849 {
850         struct smfs_plugin * plg = NULL;
851         struct kml_priv * priv = arg;
852         ENTRY;
853
854         plg = smfs_deregister_plugin(sb, SMFS_PLG_KML);
855         if (plg)
856                 OBD_FREE(plg, sizeof(*plg));
857         else
858                 CERROR("Cannot find KLM plugin while unregistering\n");
859         
860         if (priv)
861                 OBD_FREE(priv, sizeof(*priv));
862         
863         EXIT;
864         return 0;
865 }
866
867 int smfs_init_kml(struct super_block *sb)
868 {
869         int rc = 0;
870         struct kml_priv * priv = NULL;
871         struct smfs_plugin * plg = NULL;
872         ENTRY;
873         
874         OBD_ALLOC(plg, sizeof(*plg));
875         if (!plg) {
876                 rc = -ENOMEM;
877                 goto exit;
878         }
879         
880         plg->plg_type = SMFS_PLG_KML;
881         plg->plg_pre_op = NULL;
882         plg->plg_post_op = smfs_kml_post_op;
883         plg->plg_helper = smfs_kml_help_op;
884         plg->plg_exit = smfs_exit_kml;
885                 
886         OBD_ALLOC(priv, sizeof(*priv));
887         if (!priv) {
888                 rc = -ENOMEM;
889                 goto exit;
890         }
891
892         plg->plg_private = priv;
893
894         rc = smfs_register_plugin(sb, plg);
895         if (!rc) 
896                 RETURN(0);
897 exit: 
898         if (priv)
899                 OBD_FREE(priv, sizeof(*priv));
900         
901         if (plg)
902                 OBD_FREE(plg, sizeof(*plg));
903
904         RETURN(rc);
905 }
906
907