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