Whamcloud - gitweb
- landing b_fid.
[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 {
281         char *set_lmm = NULL;
282         int  rc = 0;
283         ENTRY;
284
285         if (!SMFS_DO_REC(S2SMI(inode->i_sb)))
286                 RETURN(0);
287
288         if (lmm) {
289                 OBD_ALLOC(set_lmm, lmm_size + sizeof(lmm_size));
290                 if (!set_lmm)
291                         RETURN(-ENOMEM);
292                 memcpy(set_lmm, &lmm_size, sizeof(lmm_size));
293                 memcpy(set_lmm + sizeof(lmm_size), lmm, lmm_size);
294                 rc = smfs_post_rec_setattr(inode, NULL, NULL, set_lmm);
295                 if (rc) {
296                         CERROR("Error: Record md for inode %lu rc=%d\n",
297                                 inode->i_ino, rc);
298                 }
299         }
300         if (set_lmm)
301                 OBD_FREE(set_lmm, lmm_size + sizeof(lmm_size));
302         RETURN(rc);
303 }
304 EXPORT_SYMBOL(smfs_rec_md);
305
306 int smfs_rec_precreate(struct dentry *dentry, int *num, struct obdo *oa)
307 {
308        return smfs_post_rec_create(dentry->d_inode, dentry, num, oa);
309 }
310 EXPORT_SYMBOL(smfs_rec_precreate);
311
312 int smfs_process_rec(struct super_block *sb,
313                      int count, char *dir, int flags)
314 {
315         struct llog_ctxt *ctxt;
316         struct llog_handle *loghandle;
317         struct smfs_proc_args args;
318         int rc = 0;
319         ENTRY;
320
321         if (!SMFS_INIT_REC(S2SMI(sb))) {
322                 CWARN("Did not start up rec server \n");
323                 RETURN(rc);
324         }
325
326         memset(&args, 0, sizeof(struct smfs_proc_args));
327         args.sr_sb = sb;
328         args.sr_count = count;
329         args.sr_data = dir;
330         args.sr_flags = flags ;
331         ctxt = S2SMI(sb)->smsi_rec_log;
332         loghandle = ctxt->loc_handle;
333
334         if (count == 0) {
335                 if (SMFS_DO_REINT_REC(flags)) {
336                         struct llog_gen_rec *lgr;
337
338                         /* for reint rec, we need insert a gen rec to identify
339                          * the end of the rec.*/
340                         OBD_ALLOC(lgr, sizeof(*lgr));
341                         if (!lgr)
342                                 RETURN(-ENOMEM);
343                         lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len = sizeof(*lgr);
344                         lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
345                         lgr->lgr_gen = ctxt->loc_gen;
346                         rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1,
347                                       NULL, NULL, NULL);
348                         OBD_FREE(lgr, sizeof(*lgr));
349                         if (rc != 1)
350                                 RETURN(rc);
351                 }
352         } else {
353                 SET_REC_COUNT_FLAGS(args.sr_flags, SMFS_REC_ALL);
354         }
355         if (loghandle) {
356                 if (SMFS_DO_REINT_REC(flags))
357                         rc = llog_cat_process(loghandle, ctxt->llog_proc_cb,
358                                               (void *)&args);
359                 else
360                         rc = llog_cat_reverse_process(loghandle,
361                                                       ctxt->llog_proc_cb,
362                                                       (void *)&args);
363                 if (rc == LLOG_PROC_BREAK)
364                         rc = 0;
365         }
366         RETURN(rc);
367 }
368
369 /*smfs_path is gotten from intermezzo*/
370 static char* smfs_path(struct dentry *dentry, struct dentry *root, char *buffer,
371                        int buflen)
372 {
373         char * end = buffer + buflen;
374         char * name = buffer;
375         char * buf_end = buffer + buflen;
376         char * retval;
377
378         *--end = '\0';
379         buflen--;
380         /* Get '/' right */
381         retval = end-1;
382         *retval = '/';
383
384         for (;;) {
385                 struct dentry * parent;
386                 int namelen;
387
388                 if (dentry == root)
389                         break;
390                 parent = dentry->d_parent;
391                 if (dentry == parent)
392                         break;
393                 namelen = dentry->d_name.len;
394                 buflen -= namelen + 1;
395                 if (buflen < 0)
396                         break;
397                 end -= namelen;
398                 memcpy(end, dentry->d_name.name, namelen);
399                 *--end = '/';
400                 retval = end;
401                 dentry = parent;
402         }
403         
404         while (end != buf_end) 
405                 *name++ = *end++;
406         *name = '\0'; 
407         return retval;
408 }
409
410 static int smfs_log_path(struct super_block *sb, 
411                          struct dentry *dentry, 
412                          char   *buffer,
413                          int    buffer_len)
414 {
415         struct dentry *root=sb->s_root;
416         char *p_name = buffer + sizeof(int);
417         char *name = NULL;
418         int namelen = 0;
419         ENTRY;
420
421         if (dentry) {
422                 name = smfs_path(dentry, root, p_name, buffer_len - sizeof(int));
423                 namelen = cpu_to_le32(strlen(p_name));
424                 memcpy(buffer, &namelen, sizeof(int));        
425         }
426         namelen += sizeof(int);
427         RETURN(namelen);
428 }
429
430 static inline int log_it(char *buffer, void *data, int length)
431 {
432         memcpy(buffer, &length, sizeof(int));
433         memcpy(buffer + sizeof(int), data, length);
434         return (sizeof(int) + length);                 
435 }
436
437 static int smfs_pack_rec (char *buffer, struct dentry *dentry, 
438                           struct inode *dir, void *data1, 
439                           void *data2, int op)
440
441         smfs_pack_rec_func pack_func;        
442
443         pack_func = smfs_get_rec_pack_type(dir->i_sb);
444         if (!pack_func)
445                 return 0;
446         return pack_func(buffer, dentry, dir, data1, data2, op);
447 }
448
449 int smfs_post_rec_create(struct inode *dir, struct dentry *dentry,
450                          void *data1, void *data2)
451 {
452         struct smfs_super_info *sinfo;
453         char   *buffer = NULL, *pbuf;
454         int rc = 0, length = 0, buf_len = 0;
455         ENTRY;
456         
457         sinfo = S2SMI(dentry->d_inode->i_sb);
458         if (!sinfo)
459                 RETURN(-EINVAL);
460         
461         OBD_ALLOC(buffer, PAGE_SIZE);
462         if (!buffer)
463                 GOTO(exit, rc = -ENOMEM);        
464
465         buf_len = PAGE_SIZE;
466         KML_BUF_REC_INIT(buffer, pbuf, buf_len);
467         rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
468         if (rc < 0)
469                 GOTO(exit, rc);
470         length = rc;
471         KML_BUF_REC_END(buffer, length, pbuf);   
472        
473         rc = smfs_pack_rec(pbuf, dentry, dir, 
474                            data1, data2, REINT_CREATE);
475         if (rc <= 0)
476                 GOTO(exit, rc);
477         else
478                 length += rc;
479         rc = smfs_llog_add_rec(sinfo, (void*)buffer, length); 
480 exit:
481         if (buffer)
482                 OBD_FREE(buffer, PAGE_SIZE);        
483         
484         RETURN(rc);
485 }
486
487 static int smfs_post_rec_link(struct inode *dir, struct dentry *dentry, 
488                               void *data1, void *data2)
489 {
490         struct dentry *new_dentry = (struct dentry *)data1;
491         int rc = 0, length = 0, buf_len = 0;
492         char *buffer = NULL, *pbuf = NULL;
493         struct smfs_super_info *sinfo;
494         ENTRY;
495         
496         sinfo = S2SMI(dir->i_sb);
497         if (!sinfo)
498                 RETURN(-EINVAL);
499         OBD_ALLOC(buffer, PAGE_SIZE);
500         if (!buffer)
501                 GOTO(exit, rc = -ENOMEM);
502         
503         buf_len = PAGE_SIZE;
504         KML_BUF_REC_INIT(buffer, pbuf, buf_len);
505         
506         rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
507         if (rc < 0)
508                 GOTO(exit, rc);
509         
510         length = rc;
511         KML_BUF_REC_END(buffer, length, pbuf);  
512         
513         rc = smfs_pack_rec(pbuf, dentry, dir, dentry, 
514                            new_dentry, REINT_LINK);
515         if (rc <= 0)
516                 GOTO(exit, rc);
517         
518         length += rc;
519         rc = smfs_llog_add_rec(sinfo, (void *)buffer, length); 
520 exit:
521         if (buffer)
522                 OBD_FREE(buffer, PAGE_SIZE);        
523         
524         RETURN(rc);
525 }
526
527 static int smfs_post_rec_unlink(struct inode *dir, struct dentry *dentry,
528                                 void *data1, void *data2)
529 {
530         struct smfs_super_info *sinfo;
531         int mode = *((int*)data1);
532         char   *buffer = NULL, *pbuf = NULL;
533         int  length = 0, rc = 0, buf_len = 0;
534         ENTRY;
535          
536         sinfo = S2SMI(dentry->d_inode->i_sb);
537         if (!sinfo)
538                 RETURN(-EINVAL);
539         
540         OBD_ALLOC(buffer, PAGE_SIZE);
541         if (!buffer)
542                 GOTO(exit, rc = -ENOMEM);        
543       
544         buf_len = PAGE_SIZE;
545         KML_BUF_REC_INIT(buffer, pbuf, buf_len);        
546         rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
547         if (rc < 0)
548                 GOTO(exit, rc);
549
550         length = rc;
551         KML_BUF_REC_END(buffer, length, pbuf);
552         rc = smfs_pack_rec(pbuf, dentry, dir, 
553                            &mode, NULL, REINT_UNLINK);
554         if (rc <= 0)
555                 GOTO(exit, rc);
556         else
557                 length += rc;         
558         
559         rc = smfs_llog_add_rec(sinfo, (void*)buffer, length); 
560 exit:
561         if (buffer)
562                 OBD_FREE(buffer, PAGE_SIZE);        
563         
564         RETURN(rc);
565 }
566
567 static int smfs_post_rec_rename(struct inode *dir, struct dentry *dentry, 
568                                 void *data1, void *data2)
569 {
570         struct smfs_super_info *sinfo;
571         struct inode *new_dir = (struct inode *)data1;
572         struct dentry *new_dentry = (struct dentry *)data2;
573         char *buffer = NULL, *pbuf = NULL;
574         int rc = 0, length = 0, buf_len = 0;
575         ENTRY;
576         
577         sinfo = S2SMI(dir->i_sb);
578         if (!sinfo)
579                 RETURN(-EINVAL);
580
581         OBD_ALLOC(buffer, PAGE_SIZE);
582         if (!buffer)
583                 GOTO(exit, rc = -ENOMEM);
584         
585         buf_len = PAGE_SIZE;
586         KML_BUF_REC_INIT(buffer, pbuf, buf_len);        
587         rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
588         if (rc < 0)
589                 GOTO(exit, rc);
590
591         pbuf += rc; 
592         length += rc;
593         buf_len -= rc;
594         
595         /* record new_dentry path. */
596         rc = smfs_log_path(dir->i_sb, new_dentry, pbuf, buf_len);
597         if (rc < 0)
598                 GOTO(exit, rc);
599
600         length += rc;
601         KML_BUF_REC_END(buffer, length, pbuf);
602                
603         rc = smfs_pack_rec(pbuf, dentry, dir, 
604                            new_dir, new_dentry, REINT_RENAME);
605         if (rc <= 0) 
606                 GOTO(exit, rc);
607         length += rc;
608         
609         rc = smfs_llog_add_rec(sinfo, (void*)buffer, length); 
610 exit:
611         if (buffer)
612                 OBD_FREE(buffer, PAGE_SIZE);
613         RETURN(rc);
614 }
615
616 static int smfs_insert_extents_ea(struct inode *inode, size_t from, loff_t num)
617 {
618         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
619         int rc = 0;
620         ENTRY;
621         
622         if (SMFS_INODE_OVER_WRITE(inode))
623                 RETURN(rc);
624         
625         rc = fsfilt->fs_insert_extents_ea(inode, OFF2BLKS(from, inode), 
626                                           SIZE2BLKS(num, inode));        
627         RETURN(rc);
628 }
629
630 static int smfs_remove_extents_ea(struct inode *inode, size_t from, loff_t num)
631 {
632         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
633         int rc = 0;
634         ENTRY;
635         
636         rc = fsfilt->fs_remove_extents_ea(inode, OFF2BLKS(from, inode), 
637                                           SIZE2BLKS(num, inode));        
638         
639         RETURN(rc);
640 }
641
642 static int smfs_remove_all_extents_ea(struct inode *inode)
643 {
644         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
645         int rc = 0;
646         ENTRY;
647         
648         rc = fsfilt->fs_remove_extents_ea(inode, 0, 0xffffffff);        
649         RETURN(rc);
650 }
651 static int  smfs_init_extents_ea(struct inode *inode)
652 {
653         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
654         int rc = 0;
655         ENTRY;
656         
657         rc = fsfilt->fs_init_extents_ea(inode);        
658         
659         RETURN(rc);
660 }
661 static int smfs_set_dirty_flags(struct inode *inode, int flags)
662 {
663         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
664         void   *handle;
665         int    rc = 0;
666         ENTRY;
667
668         if (SMFS_INODE_OVER_WRITE(inode))
669                 RETURN(rc);
670         /*FIXME later, the blocks needed in journal here will be recalculated*/
671          handle = smfs_trans_start(inode, FSFILT_OP_SETATTR, NULL);
672         if (IS_ERR(handle)) {
673                 CERROR("smfs_set_dirty_flag:no space for transaction\n");
674                 RETURN(-ENOSPC);
675         }
676         if ((!SMFS_INODE_DIRTY_WRITE(inode) && (!SMFS_INODE_OVER_WRITE(inode))) || 
677              ((flags == SMFS_OVER_WRITE) && (SMFS_INODE_DIRTY_WRITE(inode)))) {        
678                 rc = fsfilt->fs_set_xattr(inode, handle, REINT_EXTENTS_FLAGS,
679                                             &flags, sizeof(int));
680                 if (rc)
681                         GOTO(out, rc);
682         }
683         if (flags == SMFS_OVER_WRITE)
684                 SMFS_SET_INODE_OVER_WRITE(inode);
685         else
686                 SMFS_SET_INODE_DIRTY_WRITE(inode);
687 out:
688         smfs_trans_commit(inode, handle, 0);
689         RETURN(rc);
690 }
691
692 int smfs_post_rec_setattr(struct inode *inode, struct dentry *dentry, 
693                           void  *data1, void  *data2)
694 {        
695         struct smfs_super_info *sinfo;
696         struct iattr *attr = (struct iattr *)data1;
697         char   *buffer = NULL, *pbuf;
698         int rc = 0, length = 0, buf_len = 0;
699         ENTRY;
700
701         sinfo = S2SMI(inode->i_sb);
702         if (!sinfo)
703                 RETURN(-EINVAL);
704         
705         OBD_ALLOC(buffer, PAGE_SIZE);
706         if (!buffer)
707                 GOTO(exit, rc = -ENOMEM);        
708
709         buf_len = PAGE_SIZE;
710         KML_BUF_REC_INIT(buffer, pbuf, buf_len);        
711         rc = smfs_log_path(inode->i_sb, dentry, pbuf, buf_len);
712         if (rc < 0)
713                 GOTO(exit, rc);
714         
715         length = rc;
716         KML_BUF_REC_END(buffer, length, pbuf);
717         
718         rc = smfs_pack_rec(pbuf, dentry, inode, 
719                            data1, data2, REINT_SETATTR);
720         if (rc <= 0) 
721                 GOTO(exit, rc);
722         else
723                 length += rc;
724
725         rc = smfs_llog_add_rec(sinfo, (void*)buffer, length); 
726         if (!rc) {
727                 if (attr && attr->ia_valid & ATTR_SIZE) {
728                         smfs_remove_extents_ea(inode, attr->ia_size,
729                                                0xffffffff);                                
730                         if (attr->ia_size == 0)
731                                 smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
732                         else
733                                 smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
734                 }
735         }
736 exit:
737         if (buffer)
738                 OBD_FREE(buffer, PAGE_SIZE);        
739         RETURN(rc);
740 }
741  
742 static int all_blocks_present_ea(struct inode *inode)
743 {
744         int rc = 0;
745         ENTRY;
746         RETURN(rc);        
747 }
748
749 int smfs_post_rec_write(struct inode *dir, struct dentry *dentry, void *data1, 
750                         void *data2)
751 {
752         struct smfs_super_info *sinfo;
753         char   *buffer = NULL, *pbuf;
754         int rc = 0, length = 0, buf_len = 0;
755         ENTRY;
756         
757         if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) && 
758             !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) {
759                 sinfo = S2SMI(dentry->d_inode->i_sb);
760                 if (!sinfo)
761                         RETURN(-EINVAL);
762                 
763                 OBD_ALLOC(buffer, PAGE_SIZE);
764                 if (!buffer)
765                         GOTO(exit, rc = -ENOMEM);        
766                 
767                 buf_len = PAGE_SIZE;
768                 KML_BUF_REC_INIT(buffer, pbuf, buf_len);        
769                 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
770                 
771                 if (rc < 0)
772                         GOTO(exit, rc);
773                 pbuf += rc;
774                 memcpy(buffer, &rc, sizeof(int));        
775                 length = rc + sizeof(int);
776                         
777                 rc = smfs_pack_rec(pbuf, dentry, dir, 
778                                    data1, data2, REINT_WRITE);
779                 if (rc <= 0) 
780                         GOTO(exit, rc);
781                 else
782                         length += rc;
783  
784                 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
785                 if (rc)
786                         GOTO(exit, rc);
787                 rc = smfs_init_extents_ea(dentry->d_inode);
788                 if (rc)
789                         GOTO(exit, rc);
790         } 
791         if (dentry->d_inode->i_size == 0) {
792                 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);        
793         } else {
794                 /*insert extent EA*/
795                 loff_t off = *((loff_t*)data1);        
796                 size_t count = *((size_t*)data2);
797                 
798                 rc = smfs_insert_extents_ea(dentry->d_inode, off, count);        
799                 if (rc < 0)  
800                         GOTO(exit, rc);        
801                 if (all_blocks_present_ea(dentry->d_inode)){
802                         smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);        
803                         smfs_remove_all_extents_ea(dentry->d_inode);
804                 } else {
805                         smfs_set_dirty_flags(dentry->d_inode, SMFS_DIRTY_WRITE);        
806                 }
807         }
808 exit:
809         if (buffer)
810                 OBD_FREE(buffer, PAGE_SIZE);
811         RETURN(rc);
812 }
813
814 typedef int (*post_kml_rec)(struct inode *dir, struct dentry *dentry,
815                            void *data1, void *data2);
816
817 static post_kml_rec smfs_kml_post[HOOK_MAX + 1] = {
818         [HOOK_CREATE]  smfs_post_rec_create,
819         [HOOK_LOOKUP]  NULL,
820         [HOOK_LINK]    smfs_post_rec_link,
821         [HOOK_UNLINK]  smfs_post_rec_unlink,
822         [HOOK_SYMLINK] smfs_post_rec_create,
823         [HOOK_MKDIR]   smfs_post_rec_create,
824         [HOOK_RMDIR]   smfs_post_rec_unlink,
825         [HOOK_MKNOD]   smfs_post_rec_create,
826         [HOOK_RENAME]  smfs_post_rec_rename,
827         [HOOK_SETATTR] smfs_post_rec_setattr,
828         [HOOK_WRITE]   smfs_post_rec_write,
829         [HOOK_READDIR] NULL,
830 };
831 static int smfs_post_kml_rec(struct inode *dir, void *de, void *data1, 
832                              void *data2, int op)
833 {
834         if (smfs_kml_post[op]) {
835                 struct dentry *dentry = (struct dentry *)de;
836                 return smfs_kml_post[op](dir, dentry, data1, data2);
837         }
838         return 0;
839 }