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