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