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