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