Whamcloud - gitweb
b=10163
[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
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
365 static int smfs_set_dirty_flags(struct inode *inode, int flags)
366 {
367         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
368         void   *handle;
369         int    rc = 0;
370         ENTRY;
371
372         if (SMFS_INODE_OVER_WRITE(inode))
373                 RETURN(rc);
374         /*FIXME later, the blocks needed in journal here will be recalculated*/
375          handle = smfs_trans_start(inode, FSFILT_OP_SETATTR);
376         if (IS_ERR(handle)) {
377                 CERROR("smfs_set_dirty_flag:no space for transaction\n");
378                 RETURN(-ENOSPC);
379         }
380         if ((!SMFS_INODE_DIRTY_WRITE(inode) && (!SMFS_INODE_OVER_WRITE(inode))) || 
381              ((flags == SMFS_OVER_WRITE) && (SMFS_INODE_DIRTY_WRITE(inode)))) {        
382                 rc = fsfilt->fs_set_xattr(inode, handle, REINT_EXTENTS_FLAGS,
383                                             &flags, sizeof(int));
384                 if (rc)
385                         GOTO(out, rc);
386         }
387         if (flags == SMFS_OVER_WRITE)
388                 SMFS_SET_INODE_OVER_WRITE(inode);
389         else
390                 SMFS_SET_INODE_DIRTY_WRITE(inode);
391 out:
392         smfs_trans_commit(inode, handle, 0);
393         RETURN(rc);
394 }
395
396 static int all_blocks_present_ea(struct inode *inode)
397 {
398         int rc = 0;
399         ENTRY;
400         RETURN(rc);        
401 }
402 #endif
403
404 /* new plugin API */
405 #if 0
406 static int kml_pack_path (char **buf, struct dentry * dentry)
407 {
408         char *pbuf;
409         int length = 0, rc = 0;
410         
411         OBD_ALLOC(*buf, PAGE_SIZE);
412         if (*buf == NULL)
413                 return -ENOMEM;        
414
415         length = PAGE_SIZE;
416         KML_BUF_REC_INIT(*buf, pbuf, length);
417         rc = smfs_log_path(dentry->d_sb, dentry, pbuf, length);
418         if (rc < 0) {
419                 return rc;
420         }
421         
422         length = rc;
423         KML_BUF_REC_END(*buf, length, pbuf);  
424         
425         return length;
426 }
427 #endif
428
429 static int kml_create(struct inode *inode, void *arg,
430                       struct kml_priv *priv) 
431 {
432         struct hook_msg * msg = arg;
433         //return smfs_post_rec_create(inode, msg->dentry, NULL, NULL);
434         struct smfs_super_info *smb = S2SMI(inode->i_sb);
435         char   *buffer = NULL;
436         int rc = 0, length = 0;
437         ENTRY;
438         
439         OBD_ALLOC(buffer, PAGE_SIZE);
440         if (buffer == NULL)
441                 return -ENOMEM;    
442         
443         /*
444         rc = kml_pack_path(&buffer, msg->dentry);
445         if (rc < 0)
446                 goto exit;
447         
448         length = rc;
449         pbuf = buffer + length;
450         */        
451         rc = priv->pack_fn(REINT_CREATE, buffer, msg->dentry, inode,
452                            NULL, NULL);
453         if (rc <= 0)
454                 GOTO(exit, rc);
455         
456         length += rc;
457         rc = smfs_llog_add_rec(smb, (void*)buffer, length); 
458 exit:
459         if (buffer)
460                 OBD_FREE(buffer, PAGE_SIZE);        
461         
462         RETURN(rc);
463 }
464
465 static int kml_link(struct inode *inode, void *arg, struct kml_priv *priv) 
466 {
467         struct hook_link_msg *msg = arg;
468         int rc = 0, length = 0;
469         char *buffer = NULL;
470         ENTRY;
471         
472         OBD_ALLOC(buffer, PAGE_SIZE);
473         if (!buffer)
474                 GOTO(exit, rc = -ENOMEM);
475         
476         rc = priv->pack_fn(REINT_LINK, buffer, msg->dentry, inode, 
477                            msg->dentry, msg->new_dentry);
478         if (rc <= 0)
479                 GOTO(exit, rc);
480         
481         length += rc;
482         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void *)buffer, length); 
483 exit:
484         if (buffer)
485                 OBD_FREE(buffer, PAGE_SIZE);        
486         
487         RETURN(rc);
488 }
489
490 static int kml_unlink(struct inode * inode, void *arg, struct kml_priv * priv) 
491 {
492         struct hook_unlink_msg * msg = arg;
493         char   *buffer = NULL;
494         int  length = 0, rc = 0;
495         ENTRY;
496          
497         OBD_ALLOC(buffer, PAGE_SIZE);
498         if (!buffer)
499                 GOTO(exit, rc = -ENOMEM);        
500       
501         rc = priv->pack_fn(REINT_UNLINK, buffer, msg->dentry, inode, 
502                            &msg->mode, NULL);
503         if (rc <= 0)
504                 GOTO(exit, rc);
505         
506         length += rc;         
507         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void*)buffer, length); 
508 exit:
509         if (buffer)
510                 OBD_FREE(buffer, PAGE_SIZE);        
511         
512         RETURN(rc);
513 }
514
515 static int kml_symlink(struct inode *inode, void *arg, struct kml_priv *priv) 
516 {
517         struct smfs_super_info *smb = S2SMI(inode->i_sb);
518         struct hook_symlink_msg *msg = arg;
519         int rc = 0, length = 0;
520         char *buffer = NULL;
521         ENTRY;
522         
523         OBD_ALLOC(buffer, PAGE_SIZE);
524         if (!buffer)
525                 GOTO(exit, rc = -ENOMEM);        
526
527         rc = priv->pack_fn(REINT_CREATE, buffer, msg->dentry, inode,
528                            msg->symname, &msg->tgt_len);
529         if (rc <= 0)
530                 GOTO(exit, rc);
531         
532         length += rc;
533         rc = smfs_llog_add_rec(smb, (void*)buffer, length); 
534 exit:
535         if (buffer)
536                 OBD_FREE(buffer, PAGE_SIZE);        
537         
538         RETURN(rc);
539 }
540
541 static int kml_rename(struct inode *inode, void *arg, struct kml_priv *priv) 
542 {
543         struct hook_rename_msg *msg = arg;
544         int rc = 0, length = 0;
545         char *buffer = NULL;
546         ENTRY;
547         
548         OBD_ALLOC(buffer, PAGE_SIZE);
549         if (!buffer)
550                 GOTO(exit, rc = -ENOMEM);
551         
552         rc = priv->pack_fn(REINT_RENAME, buffer, msg->dentry, inode, 
553                            msg->new_dir, msg->new_dentry);
554         if (rc <= 0) 
555                 GOTO(exit, rc);
556         length += rc;
557         
558         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void*)buffer, length); 
559 exit:
560         if (buffer)
561                 OBD_FREE(buffer, PAGE_SIZE);
562         RETURN(rc);
563 }
564
565 static int kml_setattr(struct inode *inode, void *arg, struct kml_priv *priv) 
566 {
567         struct hook_attr_msg *msg = arg;
568         int rc = 0, length = 0;
569         char *buffer = NULL;
570         ENTRY;
571
572         OBD_ALLOC(buffer, PAGE_SIZE);
573         if (!buffer)
574                 GOTO(exit, rc = -ENOMEM);        
575
576         rc = priv->pack_fn(REINT_SETATTR, buffer, msg->dentry, inode, 
577                            msg->attr, NULL);
578         if (rc <= 0) 
579                 GOTO(exit, rc);
580         
581         length += rc;
582         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void *)buffer, length); 
583         /*
584         if (!rc) {
585                 if (attr && attr->ia_valid & ATTR_SIZE) {
586                         smfs_remove_extents_ea(inode, attr->ia_size,
587                                                0xffffffff);                                
588                         if (attr->ia_size == 0)
589                                 smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
590                         else
591                                 smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
592                 }
593         }
594         */
595 exit:
596         if (buffer)
597                 OBD_FREE(buffer, PAGE_SIZE);        
598         RETURN(rc);
599 }
600
601 static int kml_setxattr(struct inode *inode, void *arg, struct kml_priv *priv) 
602 {
603         struct hook_xattr_msg *msg = arg;
604         struct kml_buffer kbuf;
605         int rc = 0, length = 0;
606         char *buffer = NULL;
607         ENTRY;
608
609         OBD_ALLOC(buffer, PAGE_SIZE);
610         if (!buffer)
611                 GOTO(exit, rc = -ENOMEM);        
612
613         kbuf.buf = msg->buffer;
614         kbuf.buf_size = msg->buffer_size;
615
616         rc = priv->pack_fn(REINT_SETXATTR, buffer, NULL, inode,
617                            msg->name, &kbuf);
618         if (rc <= 0) 
619                 GOTO(exit, rc);
620         
621         length += rc;
622         rc = smfs_llog_add_rec(S2SMI(inode->i_sb), (void *)buffer, length); 
623         /*
624         if (!rc) {
625                 if (attr && attr->ia_valid & ATTR_SIZE) {
626                         smfs_remove_extents_ea(inode, attr->ia_size,
627                                                0xffffffff);                                
628                         if (attr->ia_size == 0)
629                                 smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
630                         else
631                                 smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
632                 }
633         }
634         */
635 exit:
636         if (buffer)
637                 OBD_FREE(buffer, PAGE_SIZE);        
638         RETURN(rc);
639 }
640
641 /*
642 static int kml_write(struct inode * inode, void *arg, struct kml_priv * priv) 
643 {
644         struct hook_write_msg * msg = arg;
645         //return smfs_post_rec_write(inode, msg->dentry, &msg->count, &msg->pos);
646         struct smfs_super_info *sinfo;
647         char   *buffer = NULL, *pbuf;
648         int rc = 0, length = 0, buf_len = 0;
649         ENTRY;
650         
651         if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) && 
652             !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) {
653                 sinfo = S2SMI(dentry->d_inode->i_sb);
654                 if (!sinfo)
655                         RETURN(-EINVAL);
656                 
657                 OBD_ALLOC(buffer, PAGE_SIZE);
658                 if (!buffer)
659                         GOTO(exit, rc = -ENOMEM);        
660                 
661                 buf_len = PAGE_SIZE;
662                 KML_BUF_REC_INIT(buffer, pbuf, buf_len);        
663                 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
664                 
665                 if (rc < 0)
666                         GOTO(exit, rc);
667                 pbuf += rc;
668                 memcpy(buffer, &rc, sizeof(int));        
669                 length = rc + sizeof(int);
670                         
671                 rc = smfs_pack_rec(pbuf, dentry, dir, 
672                                    data1, data2, REINT_WRITE);
673                 if (rc <= 0) 
674                         GOTO(exit, rc);
675                 else
676                         length += rc;
677  
678                 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
679                 if (rc)
680                         GOTO(exit, rc);
681                 rc = smfs_init_extents_ea(dentry->d_inode);
682                 if (rc)
683                         GOTO(exit, rc);
684         } 
685         if (dentry->d_inode->i_size == 0) {
686                 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);        
687         } else {
688                 //insert extent EA
689                 loff_t off = *((loff_t*)data1);        
690                 size_t count = *((size_t*)data2);
691                 
692                 rc = smfs_insert_extents_ea(dentry->d_inode, off, count);        
693                 if (rc < 0)  
694                         GOTO(exit, rc);        
695                 if (all_blocks_present_ea(dentry->d_inode)){
696                         smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);        
697                         smfs_remove_all_extents_ea(dentry->d_inode);
698                 } else {
699                         smfs_set_dirty_flags(dentry->d_inode, SMFS_DIRTY_WRITE);        
700                 }
701         }
702 exit:
703         if (buffer)
704                 OBD_FREE(buffer, PAGE_SIZE);
705         RETURN(rc);
706 }
707 */
708
709 typedef int (*post_kml_op)(struct inode *inode, void *msg,
710                            struct kml_priv *priv);
711
712 static post_kml_op smfs_kml_post[HOOK_MAX] = {
713         [HOOK_CREATE]  kml_create,
714         [HOOK_LOOKUP]  NULL,
715         [HOOK_LINK]    kml_link,
716         [HOOK_UNLINK]  kml_unlink,
717         [HOOK_SYMLINK] kml_symlink,
718         [HOOK_MKDIR]   kml_create,
719         [HOOK_RMDIR]   kml_unlink,
720         [HOOK_MKNOD]   kml_create,
721         [HOOK_RENAME]  kml_rename,
722         [HOOK_SETATTR] kml_setattr,
723         [HOOK_WRITE]   NULL,
724         [HOOK_READDIR] NULL,
725         [HOOK_F_SETXATTR] kml_setxattr,
726 };
727
728 static int smfs_kml_post_op(hook_op code, struct inode * inode,
729                             void * msg, int ret, void * priv)
730 {
731         int rc = 0;
732         
733         ENTRY;
734         
735         //check if inode has flag for KML               
736         if (!SMFS_IS(I2SMI(inode)->smi_flags, SMFS_PLG_KML))
737                 RETURN(0);
738  
739         //KML don't handle failed ops
740         if (ret)
741                 RETURN(0);
742
743         if (smfs_kml_post[code]) {
744                 CDEBUG(D_INODE,"KML: inode %lu, code: %u\n",
745                        inode->i_ino, code);
746                 rc = smfs_kml_post[code](inode, msg, priv);
747         }
748                 
749         RETURN(rc);
750 }
751
752 /* Helpers */
753 static int smfs_trans_kml (struct super_block *sb, void *arg,
754                            struct kml_priv * priv)
755 {
756         int size = 1;
757         ENTRY;
758         
759         /* FIXME-MIKE: pass fs opcode and see if kml can participate or not one
760          * record in log per operation size = 1 */
761
762         RETURN(size);
763 }
764
765 static int smfs_start_kml(struct super_block *sb, void *arg,
766                           struct kml_priv *kml_p)
767 {
768         struct smfs_super_info *smb = S2SMI(sb);
769         struct llog_ctxt **ctxt = &smb->smsi_kml_log;
770         struct obd_device *obd = arg;
771         int rc = 0;
772         ENTRY;
773
774         /* is plugin already activated */
775         if (SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
776                 RETURN(0);
777
778         if (obd && obd->obd_type && obd->obd_type->typ_name) {
779                 if (!strcmp(obd->obd_type->typ_name, OBD_MDS_DEVICENAME)) {
780                         kml_p->pack_fn = mds_rec_pack;
781                 } else if (!strcmp(obd->obd_type->typ_name, OBD_FILTER_DEVICENAME)) {
782                         kml_p->pack_fn = ost_rec_pack;
783                 } else {
784                         CWARN("unexpected device type: %s\n", obd->obd_type->typ_name);
785                 }
786         }
787
788         LASSERT(kml_p->pack_fn != NULL);
789
790         /* this will do OBD_ALLOC() for ctxt */
791         rc = llog_catalog_setup(ctxt, KML_LOG_NAME, smb->smsi_exp,
792                                 smb->smsi_ctxt, smb->sm_fsfilt,
793                                 smb->smsi_logs_dir, smb->smsi_objects_dir);
794         if (rc) {
795                 CERROR("failed to initialize kml log list catalog %d\n", rc);
796                 RETURN(rc);
797         }
798         
799         /* connect KML ctxt to obd */
800         if (obd && smb->smsi_kml_log) {
801                 smb->smsi_kml_log->loc_idx = LLOG_REINT_ORIG_CTXT;
802                 smb->smsi_kml_log->loc_obd = obd;
803                 smb->smsi_kml_log->loc_llogs = &obd->obd_llogs;
804                 obd->obd_llogs.llog_ctxt[LLOG_REINT_ORIG_CTXT] = smb->smsi_kml_log;
805         }
806
807         SMFS_SET(smb->plg_flags, SMFS_PLG_KML);
808         RETURN(0);
809 }
810
811 int smfs_stop_kml(struct super_block *sb, void *arg,
812                   struct kml_priv * kml_p)
813 {
814         struct smfs_super_info * smb = S2SMI(sb);
815         struct llog_ctxt *ctxt = smb->smsi_kml_log;
816         struct obd_device * obd = ctxt->loc_obd;
817         ENTRY;
818
819         if (!SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
820                 RETURN(0);
821
822         SMFS_CLEAR(smb->plg_flags, SMFS_PLG_KML);
823
824         llog_catalog_cleanup(ctxt);
825         obd->obd_llogs.llog_ctxt[LLOG_REINT_ORIG_CTXT] = NULL;
826         OBD_FREE(ctxt, sizeof(*ctxt));
827         
828         RETURN(0);
829 }
830
831 typedef int (*kml_helper)(struct super_block * sb, void *msg, struct kml_priv *);
832 static kml_helper smfs_kml_helpers[PLG_HELPER_MAX] = {
833         [PLG_START]      smfs_start_kml,
834         [PLG_STOP]       smfs_stop_kml,
835         [PLG_TRANS_SIZE] smfs_trans_kml,
836         [PLG_TEST_INODE] NULL,
837         [PLG_SET_INODE]  NULL,
838 };
839
840 static int smfs_kml_help_op(int code, struct super_block * sb,
841                             void * arg, void * priv)
842 {
843         int rc = 0;
844         
845         if (smfs_kml_helpers[code])
846                 rc = smfs_kml_helpers[code](sb, arg, (struct kml_priv *) priv);
847         return rc;
848 }
849
850 static int smfs_exit_kml(struct super_block *sb, void * arg)
851 {
852         struct smfs_plugin * plg = NULL;
853         struct kml_priv * priv = arg;
854         ENTRY;
855
856         plg = smfs_deregister_plugin(sb, SMFS_PLG_KML);
857         if (plg)
858                 OBD_FREE(plg, sizeof(*plg));
859         else
860                 CERROR("Cannot find KLM plugin while unregistering\n");
861         
862         if (priv)
863                 OBD_FREE(priv, sizeof(*priv));
864         
865         EXIT;
866         return 0;
867 }
868
869 int smfs_init_kml(struct super_block *sb)
870 {
871         int rc = 0;
872         struct kml_priv * priv = NULL;
873         struct smfs_plugin * plg = NULL;
874         ENTRY;
875         
876         OBD_ALLOC(plg, sizeof(*plg));
877         if (!plg) {
878                 rc = -ENOMEM;
879                 goto exit;
880         }
881         
882         plg->plg_type = SMFS_PLG_KML;
883         plg->plg_pre_op = NULL;
884         plg->plg_post_op = smfs_kml_post_op;
885         plg->plg_helper = smfs_kml_help_op;
886         plg->plg_exit = smfs_exit_kml;
887                 
888         OBD_ALLOC(priv, sizeof(*priv));
889         if (!priv) {
890                 rc = -ENOMEM;
891                 goto exit;
892         }
893
894         plg->plg_private = priv;
895
896         rc = smfs_register_plugin(sb, plg);
897         if (!rc) 
898                 RETURN(0);
899 exit: 
900         if (priv)
901                 OBD_FREE(priv, sizeof(*priv));
902         
903         if (plg)
904                 OBD_FREE(plg, sizeof(*plg));
905
906         RETURN(rc);
907 }
908
909