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