Whamcloud - gitweb
- many fixes about using ENTRY, RETURN, GOTO and EXIT.
[fs/lustre-release.git] / lustre / smfs / smfs_cow.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #define DEBUG_SUBSYSTEM S_SM
24
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/pagemap.h>
28 #include <linux/string.h>
29 #include <linux/slab.h>
30 #include <linux/stat.h>
31 #include <linux/unistd.h>
32 #include <linux/smp_lock.h>
33 #include <linux/obd_class.h>
34 #include <linux/obd_support.h>
35 #include <linux/lustre_lib.h>
36 #include <linux/lustre_idl.h>
37 #include <linux/lustre_fsfilt.h>
38
39 #include <linux/lustre_smfs.h>
40 #include <linux/lustre_snap.h>
41
42 #include "smfs_internal.h"
43
44 #define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) +       \
45                               size * sizeof(struct snap))
46
47 int smfs_cleanup_snap_info(struct snap_info *snap_info);
48
49 static int smfs_init_snap_super_info(struct smfs_super_info *smfs_info)
50 {
51         struct snap_super_info  *snap_sinfo;
52         int rc = 0;
53
54         ENTRY;
55         
56         OBD_ALLOC(smfs_info->smsi_snap_info,
57                   sizeof(struct snap_super_info));
58         
59         if (!smfs_info->smsi_snap_info) 
60                 GOTO(exit, rc = -ENOMEM);
61
62         snap_sinfo = smfs_info->smsi_snap_info;
63
64         /*init snap fsfilt operations*/
65         if (!snap_sinfo->snap_cache_fsfilt) {
66                 char *snap_cache_ftype = NULL;
67                 int   tmp = strlen(smfs_info->smsi_cache_ftype) + strlen("_snap");
68                 
69                 OBD_ALLOC(snap_cache_ftype, tmp + 1);
70                 if (!snap_cache_ftype)
71                         GOTO(exit, rc = -ENOMEM);
72                         
73                 sprintf(snap_cache_ftype, "%s_snap", smfs_info->smsi_cache_ftype);
74                 snap_sinfo->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype);
75                 OBD_FREE(snap_cache_ftype, tmp + 1);
76                 if (!snap_sinfo->snap_cache_fsfilt) {
77                         CERROR("Can not get %s fsfilt ops needed by snap\n",
78                                snap_cache_ftype);
79                         GOTO(exit, rc = -EINVAL);
80                 }
81         }
82         if (!snap_sinfo->snap_fsfilt) {
83                 char *snap_ftype = NULL;
84                 int   tmp = strlen(smfs_info->smsi_ftype) + strlen("_snap");
85                 
86                 OBD_ALLOC(snap_ftype, tmp + 1);  
87                 if (!snap_ftype)
88                         GOTO(exit, rc = -ENOMEM);
89
90                 sprintf(snap_ftype, "%s_snap", smfs_info->smsi_ftype);
91                 snap_sinfo->snap_fsfilt = fsfilt_get_ops(snap_ftype);
92                 OBD_FREE(snap_ftype, tmp + 1);
93                 if (!snap_sinfo->snap_fsfilt) {
94                         CERROR("Can not get %s fsfilt ops needed by snap\n",
95                                snap_ftype);
96                         GOTO(exit, rc = -EINVAL);
97                 }
98         }
99         INIT_LIST_HEAD(&snap_sinfo->snap_list);
100 exit:
101         if (rc && smfs_info->smsi_snap_info)
102                 OBD_FREE(snap_sinfo, sizeof(struct snap_super_info));
103         RETURN(rc);
104 }
105 /*FIXME-wangdi Should remove it when integrated it with lustre*/
106 static struct dentry *smfs_simple_mkdir(struct dentry *dir, char *name, 
107                                         int mode, int fix)
108 {
109         struct dentry *dchild;
110         int err = 0;
111         
112         dchild = ll_lookup_one_len(name, dir, strlen(name));
113         if (IS_ERR(dchild))
114                 GOTO(out_up, dchild);
115         
116         if (dchild->d_inode) {
117                 int old_mode = dchild->d_inode->i_mode;
118                 if (!S_ISDIR(old_mode))
119                         GOTO(out_err, err = -ENOTDIR);
120                                                                                                                                                                                                      
121                 /* Fixup directory permissions if necessary */
122                 if (fix && (old_mode & S_IALLUGO) != (mode & S_IALLUGO)) {
123                         CWARN("fixing permissions on %s from %o to %o\n",
124                               name, old_mode, mode);
125                         dchild->d_inode->i_mode = (mode & S_IALLUGO) |
126                                                   (old_mode & ~S_IALLUGO);
127                         mark_inode_dirty(dchild->d_inode);
128                 }
129                 GOTO(out_up, dchild);
130         }
131         err = vfs_mkdir(dir->d_inode, dchild, mode);
132         if (err)
133                 GOTO(out_err, err);
134         RETURN(dchild);
135 out_err:
136         dput(dchild);
137         dchild = ERR_PTR(err);
138 out_up:
139         return dchild;
140
141 }
142 static struct snap_info *smfs_find_snap_info(struct inode *inode)
143 {
144         struct snap_inode_info *snap_iinfo = I2SNAPI(inode);
145         struct snap_super_info *snap_sinfo = S2SNAPI(inode->i_sb);
146         struct snap_info *snap_info = NULL, *tmp; 
147
148         ENTRY;
149         list_for_each_entry_safe(snap_info, tmp, &snap_sinfo->snap_list, 
150                                  sni_list) {
151                if (snap_info->sni_root_ino == snap_iinfo->sn_root_ino)
152                         RETURN(snap_info); 
153         }
154         RETURN(NULL);
155 }
156
157 #if 0
158 static int smfs_dotsnap_dir_size(struct inode *inode)
159 {
160         struct snap_super_info *snap_sinfo = S2SNAPI(inode->i_sb);
161         struct fsfilt_operations *snapops = snap_sinfo->snap_cache_fsfilt; 
162         int size = 0, dir_size = 0, blocks, i = 0;
163         struct snap_table *snap_table = NULL; 
164         struct snap_info *snap_info = NULL;
165         ENTRY;
166        
167         snap_info = smfs_find_snap_info(inode);
168         
169         if (!snap_info) {
170                 CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
171                 RETURN(0);                
172         }
173         snap_table = snap_info->sni_table;
174         for (i = 0; i < snap_table->sntbl_count; i++) {
175                 char *name = snap_table->sntbl_items[i].sn_name;
176                 size += snapops->fs_dir_ent_size(name);
177         }
178         /*FIXME this is only for ext3 dir format, may need fix for other FS*/ 
179         blocks = (size + inode->i_sb->s_blocksize - 1) >> 
180                                 inode->i_sb->s_blocksize_bits; 
181         
182         dir_size = blocks * inode->i_sb->s_blocksize; 
183         RETURN(dir_size); 
184
185 }
186 #endif
187
188 static int smfs_init_snap_inode_info(struct inode *inode, struct inode *dir, int index) 
189 {
190         int rc = 0;
191         ENTRY;
192
193         if (!inode)
194                 RETURN(0);
195
196         if (dir) {
197                 I2SNAPI(inode)->sn_flags = I2SNAPI(dir)->sn_flags;
198                 I2SNAPI(inode)->sn_gen = I2SNAPI(dir)->sn_gen;
199                 I2SNAPI(inode)->sn_root_ino = I2SNAPI(dir)->sn_root_ino;
200                 I2SNAPI(inode)->sn_index = I2SNAPI(inode)->sn_index; 
201         } else {
202                 I2SNAPI(inode)->sn_flags = 0;
203                 I2SNAPI(inode)->sn_gen = 0;
204         }
205         
206         I2SNAPI(inode)->sn_index = index;
207  
208         if (smfs_dotsnap_inode(inode)) {
209                 struct snap_info *snap_info;
210
211                 snap_info = smfs_find_snap_info(inode);
212                 if (!snap_info) {
213                         RETURN(-EIO);
214                 }
215                 /*init dot_snap inode info*/
216 //              inode->i_size = (loff_t)smfs_dotsnap_dir_size(inode);
217                 inode->i_size = snap_info->sni_table->sntbl_count;
218                 inode->i_nlink = snap_info->sni_table->sntbl_count + 2;
219                 inode->i_uid = 0;
220                 inode->i_gid = 0;
221         } else if (SMFS_DO_COW(S2SMI(inode->i_sb)) && 
222                    (I2SMI(inode)->smi_flags & SM_DO_COW) &&
223                    smfs_primary_inode(inode)) {
224                 struct snap_inode_info *sni_info = I2SNAPI(inode);
225                 struct fsfilt_operations *sops = I2SNAPCOPS(inode);
226                 int vallen = 0;
227  
228                 vallen = sizeof(sni_info->sn_gen);
229                 
230                 rc = sops->fs_get_snap_info(I2CI(inode), SNAP_GENERATION,
231                                             strlen(SNAP_GENERATION),
232                                             &sni_info->sn_gen, &vallen);               
233         } 
234         RETURN(rc);                                              
235 }
236
237 #define COWED_NAME_LEN       (7 + 8 + 1) 
238 static int smfs_init_cowed_dir(struct snap_info *snap_info, struct inode* inode)  
239 {
240         struct dentry    *dentry = NULL;
241         char   name[COWED_NAME_LEN];
242         int    rc = 0;
243         ENTRY;
244          
245         sprintf(name, ".cowed_%08x", (__u32)inode->i_ino);
246         /*FIXME-WANGDI: will use simple_mkdir, when integrating snap to lustre*/
247         dentry = smfs_simple_mkdir(inode->i_sb->s_root, name, 0777, 1);
248         if (IS_ERR(dentry)) {
249                 rc = PTR_ERR(dentry);
250                 CERROR("create cowed directory: rc = %d\n", rc);
251                 RETURN(rc);
252         }
253         snap_info->sni_cowed_dentry = dentry;
254         /*cleanup cowed inode attr for cowed dir*/
255         SMFS_CLEAN_INODE_COWED(dentry->d_inode);
256         RETURN(rc);
257 }
258
259 static int smfs_init_dotinfo(struct snap_info *snap_info)
260 {
261         struct snap_dot_info *dot_info = NULL;
262         int rc = 0;
263         ENTRY;
264
265         if (snap_info->sni_dot_info)
266                 RETURN(-EEXIST);
267        
268         OBD_ALLOC(snap_info->sni_dot_info, sizeof(struct snap_dot_info));
269         
270         if (!snap_info->sni_dot_info)
271                 RETURN(-ENOMEM); 
272       
273         dot_info = snap_info->sni_dot_info;
274  
275         OBD_ALLOC(dot_info->dot_name,  strlen(DOT_SNAP_NAME) + 1);
276
277         if (!dot_info->dot_name) {
278                 OBD_FREE(snap_info->sni_dot_info, sizeof(struct snap_dot_info));
279                 RETURN(-ENOMEM); 
280         } 
281         memcpy(dot_info->dot_name, DOT_SNAP_NAME, strlen(DOT_SNAP_NAME));
282         
283         dot_info->dot_name_len = strlen(DOT_SNAP_NAME); 
284         dot_info->dot_snap_enable = 1;
285         
286         RETURN(rc);
287 }
288
289 static int smfs_init_snap_info(struct smfs_super_info *smb, 
290                                struct snap_info *snap_info, struct inode *inode) 
291 {
292         struct snap_table        *snap_table = NULL;       
293         struct fsfilt_operations *snapcops;
294         int                      rc = 0, size, table_size, vallen, i;
295  
296         ENTRY;
297
298         snapcops = smb->smsi_snap_info->snap_cache_fsfilt;
299         /*Initialized table */
300         /*get the maxsize of snaptable*/
301         vallen = sizeof(int);
302         rc = snapcops->fs_get_snap_info(I2CI(inode), MAX_SNAPTABLE_COUNT,
303                                        strlen(MAX_SNAPTABLE_COUNT), &size, 
304                                        &vallen);
305         if (size == 0) {
306                 CERROR("the Max snaptable count should not be zero\n");
307                 GOTO(exit, rc);
308         }
309         table_size = SNAPTABLE_SIZE(size);
310
311         OBD_ALLOC(snap_info->sni_table, table_size);
312
313         if (!snap_info->sni_table) {
314                 CERROR("No MEM\n");
315                 RETURN(-ENOMEM);
316         }
317         snap_table = snap_info->sni_table;
318          
319         snap_table->sntbl_magic = cpu_to_le32((__u32)SNAPTABLE_MAGIC); 
320         snap_table->sntbl_max_count = size;
321         /*init sn_index to -1*/ 
322         for (i = 0; i < snap_table->sntbl_max_count; i++) 
323                 snap_table->sntbl_items[i].sn_index = -1;
324         /*get snaptable info*/
325         rc = snapcops->fs_get_snap_info(I2CI(inode), SNAPTABLE_INFO, 
326                                         strlen(SNAPTABLE_INFO), 
327                                         snap_table, &table_size);       
328         if (rc < 0) {
329                 if (rc == -ENODATA) {
330                         snap_table->sntbl_count = 0;
331                         rc = 0;
332                 } else {
333                         CERROR("Can not retrive the snaptable from this filesystem\n");
334                         GOTO(exit, rc);
335                 }
336         } else { 
337                 if (le32_to_cpu(snap_table->sntbl_magic) != SNAPTABLE_MAGIC) {
338                         CERROR("On disk snaptable is not right \n");
339                         GOTO(exit, rc = -EIO);
340                 }
341         }
342         init_MUTEX(&snap_info->sni_sema);
343         snap_info->sni_root_ino = inode->i_ino;
344         rc = smfs_init_cowed_dir(snap_info, inode);
345         if (rc) {
346                 CERROR("Init cowed dir error rc=%d\n", rc);
347                 GOTO(exit, rc); 
348         }
349         rc = smfs_init_dotinfo(snap_info);
350 exit:
351         if (rc && snap_table)
352                 OBD_FREE(snap_table, table_size);
353         RETURN(rc);
354 }
355
356 static struct snap_info *smfs_create_snap_info(struct smfs_super_info *sinfo, 
357                                                struct inode *inode)
358 {
359         struct snap_info *snap_info = NULL;
360         int rc = 0;
361         ENTRY;
362  
363         OBD_ALLOC(snap_info, sizeof(struct snap_info)); 
364         if (!snap_info) 
365                 RETURN(ERR_PTR(-ENOMEM));  
366         rc = smfs_init_snap_info(sinfo, snap_info, inode);  
367         if (rc) 
368                 GOTO(exit, rc);
369        
370         /*set cow flags for the snap root inode*/ 
371         I2SMI(inode)->smi_flags |= SM_DO_COW;
372         I2SNAPI(inode)->sn_root_ino = inode->i_ino; 
373 exit:
374         if (rc) {
375                 OBD_FREE(snap_info, sizeof(struct snap_info));
376                 snap_info = ERR_PTR(rc);
377         }
378         RETURN(snap_info);
379 }
380
381 static int smfs_cow_pre(struct inode *dir, void *dentry, void *new_dir, 
382                         void *new_dentry, int op);
383
384 static int smfs_cow_post(struct inode *dir, void *dentry, void *new_dir, 
385                          void *new_dentry, int op);
386 #define COW_HOOK "cow_hook"
387 static int smfs_cow_pre_hook(struct inode *inode, void *dentry, void *data1,
388                              void *data2, int op, void *handle)
389 {
390         int rc = 0;
391         ENTRY;
392  
393         if (smfs_do_cow(inode)) {
394                 /*FIXME:WANGDI, get index from the dentry*/
395                 #if 0
396                 int index = 0;
397                 smfs_get_dentry_name_index(dentry, &name, index);       
398                 smfs_free_dentry_name(&name);
399                 #endif
400                 rc = smfs_cow_pre(inode, dentry, data1, data2, op);           
401         }
402         RETURN(rc);                                                                     
403 }
404 static int smfs_cow_post_hook(struct inode *inode, void *dentry, void *data1, 
405                               void *data2, int op, void *handle)
406 {
407         int rc = 0;
408         ENTRY;
409  
410         if (smfs_do_cow(inode)) {
411                 rc = smfs_cow_post(inode, dentry, data1, data2, op);           
412         }
413         RETURN(rc);                                                                     
414 }
415
416 int smfs_cow_cleanup(struct smfs_super_info *smb)
417 {
418         struct snap_super_info   *snap_sinfo = smb->smsi_snap_info;
419         struct list_head         *snap_list = &snap_sinfo->snap_list; 
420         struct smfs_hook_ops     *cow_hops;
421         int                      rc = 0; 
422         ENTRY;
423
424         while (!list_empty(snap_list)) {
425                 struct snap_info *snap_info;
426                 
427                 snap_info = list_entry(snap_list->next, struct snap_info,
428                                        sni_list); 
429                 rc = smfs_cleanup_snap_info(snap_info); 
430                 if (rc) 
431                         CERROR("cleanup snap_info error rc=%d\n", rc);
432                 list_del(&snap_info->sni_list); 
433                 OBD_FREE(snap_info, sizeof(struct snap_info));
434         } 
435          
436         if (snap_sinfo->snap_fsfilt) 
437                 fsfilt_put_ops(snap_sinfo->snap_fsfilt);
438         if (snap_sinfo->snap_cache_fsfilt)
439                 fsfilt_put_ops(snap_sinfo->snap_cache_fsfilt);
440
441         cow_hops = smfs_unregister_hook_ops(smb, COW_HOOK);
442         smfs_free_hook_ops(cow_hops);
443
444         SMFS_CLEAN_COW(smb);
445         if (snap_sinfo) 
446                OBD_FREE(snap_sinfo, sizeof(struct snap_super_info));
447         RETURN(rc);
448 }
449
450 int smfs_cow_init(struct super_block *sb)
451 {
452         struct smfs_super_info *smfs_info = S2SMI(sb);
453         struct smfs_hook_ops *cow_hops = NULL;
454         struct fsfilt_operations *sops;
455         struct inode *root_inode = smfs_info->smsi_sb->s_root->d_inode; 
456         int snap_count = 0, rc = 0, vallen;
457
458         ENTRY;
459
460         SMFS_SET_COW(smfs_info);
461       
462         cow_hops = smfs_alloc_hook_ops(COW_HOOK, smfs_cow_pre_hook, 
463                                        smfs_cow_post_hook);
464         if (!cow_hops) {
465                 RETURN(-ENOMEM);
466         }
467  
468         rc = smfs_register_hook_ops(smfs_info, cow_hops);
469         if (rc) {
470                 smfs_free_hook_ops(cow_hops);
471                 RETURN(rc);
472         }
473         
474         rc = smfs_init_snap_super_info(smfs_info);
475         if (rc && cow_hops) {
476                 smfs_unregister_hook_ops(smfs_info, cow_hops->smh_name);
477                 smfs_free_hook_ops(cow_hops);
478                 RETURN(rc);
479         }
480         sops = smfs_info->smsi_snap_info->snap_cache_fsfilt; 
481         
482         vallen = sizeof(int); 
483         rc = sops->fs_get_snap_info(root_inode, SNAP_COUNT, strlen(SNAP_COUNT),
484                                     &snap_count, &vallen);
485         if (rc < 0)
486                 GOTO(exit, rc);       
487  
488         if (snap_count > 0) {
489                 int snap_root_size = snap_count * sizeof(ino_t);
490                 ino_t *snap_root;
491                 int i;
492                 
493                 OBD_ALLOC(snap_root, snap_root_size);
494                 
495                 if (!snap_root)
496                         GOTO(exit, rc = -ENOMEM); 
497                 
498                 rc = sops->fs_get_snap_info(root_inode, SNAP_ROOT_INO, 
499                                             strlen(SNAP_ROOT_INO), snap_root, 
500                                             &snap_root_size);
501                 if (rc < 0) {
502                         OBD_FREE(snap_root, sizeof(int) * snap_count);
503                         GOTO(exit, rc);
504                 }
505                 for (i = 0; i < snap_count; i++) {
506                         ino_t root_ino = le32_to_cpu(snap_root[i]);
507                         struct snap_info *snap_info;                      
508  
509                         root_inode = smfs_get_inode(sb, root_ino, NULL, 0);
510                         smfs_init_snap_inode_info(root_inode, NULL, 0);
511                         snap_info = smfs_create_snap_info(S2SMI(sb), root_inode);
512                         iput(root_inode);
513                         if (IS_ERR(snap_info)) {
514                                 OBD_FREE(snap_root, sizeof(int) * snap_count);
515                                 GOTO(exit, rc = PTR_ERR(snap_info));
516                         }                
517                         list_add(&snap_info->sni_list, 
518                                  &(S2SNAPI(sb)->snap_list));        
519                 }
520         }      
521         smfs_info->smsi_snap_info->snap_count = snap_count; 
522 exit:
523         if (rc) 
524                 smfs_cow_cleanup(smfs_info);
525         RETURN(rc);
526 }
527
528 static int smfs_cleanup_dotinfo(struct snap_info *snap_info)
529 {       
530         struct snap_dot_info *dot_info = NULL;
531         int rc = 0;
532         ENTRY;
533
534         if (!snap_info->sni_dot_info)
535                 RETURN(rc);
536        
537         dot_info = snap_info->sni_dot_info;
538
539         if (dot_info->dot_name) { 
540                 OBD_FREE(dot_info->dot_name, dot_info->dot_name_len + 1);
541         }
542         
543         OBD_FREE(dot_info, sizeof(struct snap_dot_info));
544
545         RETURN(rc);
546 }
547
548 int smfs_cleanup_snap_info(struct snap_info *snap_info)
549 {
550         struct snap_table      *snap_table = snap_info->sni_table;
551         int rc = 0, table_size;
552         ENTRY;
553
554         l_dput(snap_info->sni_cowed_dentry);
555         //d_unalloc(snap_info->sni_cowed_dentry);
556         if (snap_table) {
557                 table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count);
558                 OBD_FREE(snap_info->sni_table, table_size);
559         }
560         smfs_cleanup_dotinfo(snap_info);
561         RETURN(rc);
562 }
563
564 int smfs_snap_test_inode(struct inode *inode, void *args)
565
566         struct smfs_iget_args *sargs = (struct smfs_iget_args*)args;
567         struct inode *dir;
568
569         LASSERT(sargs);
570         
571         dir = sargs->s_inode;
572         
573         if (sargs->s_index > 0) { 
574                 if (I2SNAPI(inode)->sn_index != sargs->s_index)
575                         return 0;
576         }else {
577                 if (dir && I2SNAPI(inode)->sn_index != I2SNAPI(dir)->sn_index)
578                         return 0;
579         }
580         return 1;
581 }
582 /* latest snap: returns 
583    -  the index of the latest snapshot before NOW
584    -  hence it returns 0 in case all the volume snapshots lie in the future
585    -  this is the index where a COW will land (will be created) 
586 */
587 void snap_last(struct inode *inode, struct snap *snap)
588 {
589         time_t now = LTIME_S(CURRENT_TIME);
590         struct snap_table *snap_table;
591         struct snap_info  *snap_info;
592         int i ;
593
594         ENTRY;
595
596         snap_info = smfs_find_snap_info(inode);
597         if (!snap_info) {
598                 CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
599                 EXIT;
600                 return;
601         }
602         snap_table = snap_info->sni_table;
603         /* start at the highest index in the superblock snaptime array */ 
604         if (snap_table->sntbl_count == 0) {
605                memset(snap, 0, sizeof(struct snap)); 
606         } else {
607                 i = snap_table->sntbl_count - 1;
608                 snap->sn_index = snap_table->sntbl_items[i].sn_index;
609                 snap->sn_time = snap_table->sntbl_items[i].sn_time;
610                 snap->sn_gen = snap_table->sntbl_items[i].sn_gen;
611         }
612         CDEBUG(D_INFO, "index: %d, time[i]: %ld, now: %ld\n",
613                snap->sn_index, snap->sn_time, now);
614         EXIT;
615         return;
616 }
617
618 static inline int get_index_of_item(struct snap_table *table, char *name)
619 {
620         int count = table->sntbl_count;
621         int i, j;
622         ENTRY;
623         
624         for (i = 0; i < table->sntbl_max_count; i++) { 
625                 if (!strcmp(name, table->sntbl_items[i].sn_name)) {
626                         CERROR("Duplicate name %s in snaptable\n", name); 
627                         RETURN(-EINVAL);
628                 }       
629         }
630
631         for (i = 1; i <= table->sntbl_max_count; i++) {
632                 int found = 0;
633                 for (j = 0; j < (count + 1); j++) {
634                         if (table->sntbl_items[j].sn_index == i) {
635                                 found = 1;
636                                 break;  
637                         }
638                 }
639                 if (!found)
640                         RETURN(i);
641         }
642         CERROR("snaptable Full\n");
643         RETURN(-ENOSPC);
644 }
645
646 static struct dentry *smfs_find_snap_root(struct super_block *sb, 
647                                           char *path_name)
648 {
649         struct dentry *dentry = NULL;
650         struct nameidata nd;
651         ENTRY;
652
653 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
654         if (path_init(path_name, LOOKUP_FOLLOW, &nd)) {
655                 int error = path_walk(path_name, &nd);
656                 if (error) {
657                         path_release(&nd);
658                         RETURN(NULL);
659                 }
660         } else {
661                 RETURN(NULL);
662         }
663 #else
664         if (path_lookup(path_name, LOOKUP_FOLLOW, &nd))
665                 RETURN(NULL);
666 #endif
667         dentry = dget(nd.dentry); 
668         path_release(&nd);
669         RETURN(dentry); 
670 }
671
672 static int snap_add_item(struct smfs_super_info *smb, 
673                          struct snap_info *snap_info,
674                          char *name)
675 {        
676         struct fsfilt_operations *snapops;
677         struct snap_table        *snap_table = snap_info->sni_table;
678         struct inode             *root_inode = NULL;
679         int                      table_size, count = 0, index = 0, rc = 0;
680         struct  snap             *snap_item;
681         ENTRY;
682
683         count = snap_table->sntbl_count; 
684         root_inode = iget(smb->smsi_sb, snap_info->sni_root_ino);
685         if (!root_inode || is_bad_inode(root_inode)) 
686                 RETURN(-EIO); 
687         /* XXX Is down this sema necessary*/
688         down_interruptible(&snap_info->sni_sema);
689         snap_item = &snap_table->sntbl_items[count];
690         snapops = smb->smsi_snap_info->snap_cache_fsfilt;
691         /*add item in snap_table set generation*/
692         snap_item->sn_time = LTIME_S(CURRENT_TIME);
693         /* find table index */
694         index = get_index_of_item(snap_table, name);
695         if (index < 0) 
696                 GOTO(exit, rc = index);
697         
698         snap_item->sn_index = index;
699         snap_item->sn_flags = 0;
700         snap_item->sn_gen = snap_table->sntbl_generation + 1; 
701         memcpy(snap_item->sn_name, name, SNAP_MAX_NAMELEN);
702         /* Wrote the whole snap_table to disk */
703         table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count); 
704          
705         snap_table->sntbl_count++;
706         snap_table->sntbl_generation++;
707         rc = snapops->fs_set_snap_info(root_inode, SNAPTABLE_INFO, 
708                                        strlen(SNAPTABLE_INFO),
709                                        snap_table, &table_size);
710         if (rc) {
711                 snap_table->sntbl_count--;
712                 snap_table->sntbl_generation--;
713                 CERROR("Set snaptable error rc=%d\n", rc);
714                 GOTO(exit, rc);
715         }
716 exit:
717         up(&snap_info->sni_sema);
718         if (root_inode)
719                 iput(root_inode);
720         RETURN(rc);
721 }
722
723 static struct snap_info * smfs_find_create_snap_info(struct super_block *sb, 
724                                                      struct inode *inode) 
725 {       
726         struct snap_super_info   *snap_sinfo = S2SNAPI(sb);
727         struct fsfilt_operations *sops = snap_sinfo->snap_cache_fsfilt;
728         struct snap_info *snap_info, *tmp;
729         ino_t *snap_root = NULL;
730         int    rino_size, snap_count_size, rc = 0;
731         ENTRY;
732         
733         list_for_each_entry_safe(snap_info, tmp, &snap_sinfo->snap_list, 
734                                  sni_list) {
735                 if (snap_info->sni_root_ino == inode->i_ino) {
736                         RETURN(snap_info);
737                 }      
738         } 
739
740         CDEBUG(D_INFO, "create a new  snap info root ino %lu\n", inode->i_ino);
741
742         snap_info = smfs_create_snap_info(S2SMI(sb), inode);  
743
744         if (IS_ERR(snap_info))
745                 RETURN(snap_info);
746   
747         snap_sinfo->snap_count++;
748
749         rino_size = snap_sinfo->snap_count * sizeof(ino_t);
750
751         OBD_ALLOC(snap_root, rino_size);
752                 
753         if (!snap_root)
754                 GOTO(exit, rc = -ENOMEM); 
755                 
756         rc = sops->fs_get_snap_info(I2CI(inode), SNAP_ROOT_INO, 
757                                     strlen(SNAP_ROOT_INO), snap_root, 
758                                     &rino_size);
759         if (rc < 0) {
760                 if (rc == -ENODATA) {
761                         rc = 0;
762                 } else {
763                         GOTO(exit, rc);
764                 }
765         }
766         snap_root[snap_sinfo->snap_count - 1] = inode->i_ino;
767       
768         snap_count_size = sizeof(int);        
769         rc = sops->fs_set_snap_info(I2CI(inode), SNAP_COUNT, strlen(SNAP_COUNT), 
770                                     &snap_sinfo->snap_count,  &snap_count_size);
771         if (rc) 
772                 GOTO(exit, rc);
773        
774         rc = sops->fs_set_snap_info(I2CI(inode), SNAP_ROOT_INO,
775                                     strlen(SNAP_ROOT_INO), snap_root,
776                                     &rino_size); 
777
778         if (rc)
779                 GOTO(exit, rc);        
780
781         list_add(&snap_info->sni_list, &snap_sinfo->snap_list);        
782 exit: 
783         if (rc) {
784                 smfs_cleanup_snap_info(snap_info); 
785                 OBD_FREE(snap_info, sizeof(struct snap_info));
786         }
787         if (snap_root)
788                 OBD_FREE(snap_root, rino_size); 
789         RETURN(snap_info);  
790 }         
791
792 int smfs_add_snap_item(struct super_block *sb, char *path_name, char *name)
793 {
794         struct dentry  *dentry = NULL;
795         struct snap_info *snap_info;
796         int            rc = 0;        
797         ENTRY;
798                 
799         if (!SMFS_DO_COW(S2SMI(sb))) {
800                 RETURN(0);
801         }
802
803         if (!path_name || !name) {
804                 CERROR("patch_name and snapshot_name is NULL");
805                 RETURN(-EINVAL);
806         } 
807         dentry = smfs_find_snap_root(sb, path_name);
808         if (IS_ERR(dentry)) {
809                 CERROR("can not find snap_shot root by %s\n", path_name);
810                 RETURN(PTR_ERR(dentry)); 
811         }
812         snap_info = smfs_find_create_snap_info(sb, dentry->d_inode);
813         if (IS_ERR(snap_info)) {
814                 CERROR("can not find snap_info by %s rc=%lu\n", path_name,
815                         PTR_ERR(snap_info));
816                 GOTO(exit, rc = PTR_ERR(snap_info)); 
817         }
818
819         rc = snap_add_item(S2SMI(sb), snap_info, name);
820 exit:       
821         dput(dentry); 
822         RETURN(rc); 
823 }        
824 //EXPORT_SYMBOL(smfs_add_snap_item);
825 /*
826  * Note: this function should be differnet with snap_do_cow.
827  * In smfs_do_cow, we check the EA for whether do cow for that inode.
828  * In smfs_needs_cow, we check whether we do need to do cow. 
829  */
830 int smfs_needs_cow(struct inode *inode)
831 {
832         struct smfs_inode_info  *smi_info = I2SMI(inode); 
833         struct snap_inode_info *snap_info = NULL;
834         struct snap snap;
835         int index = -1;
836         ENTRY;
837
838         snap_info = &(smi_info->sm_sninfo);
839         
840         snap_last(inode, &snap);
841         /* decision .... if the snapshot is more recent than the object,
842          * then any change to the object should cause a COW.
843          */
844         if (snap_info->sn_gen < snap.sn_gen ) 
845                 index = snap.sn_index;
846
847         CDEBUG(D_INFO, "snap_needs_cow, ino %lu , get index %d\n",
848                inode->i_ino, index);
849
850         RETURN(index);
851 } /* snap_needs_cow */
852
853 static int link_cowed_inode(struct inode *inode)
854 {
855         struct dentry *cowed_dir = NULL;
856         char idname[LL_ID_NAMELEN];
857         struct snap_info *snap_info;    
858         int idlen = 0, rc = 0;
859         struct dentry *dchild = NULL;
860         struct dentry *tmp = NULL;
861         unsigned mode;
862
863         snap_info = smfs_find_snap_info(inode);
864         if (!snap_info) {
865                 CERROR("can not find snap info for inode %p\n", inode);
866                 RETURN(-EINVAL);                
867         }
868
869         cowed_dir = snap_info->sni_cowed_dentry;
870         
871         down(&cowed_dir->d_inode->i_sem);
872
873         idlen = ll_id2str(idname, inode->i_ino, inode->i_generation);
874         dchild = lookup_one_len(idname, cowed_dir, idlen);
875         if (IS_ERR(dchild)) {
876                 rc = PTR_ERR(dchild);
877                 if (rc != -EPERM && rc != -EACCES)
878                         CERROR("child lookup error %d\n", rc);
879                 GOTO(out_lock, rc);
880         }
881         if (dchild->d_inode != NULL) {
882                 CERROR("re-cowed file %s?\n", dchild->d_name.name);
883                 LASSERT(dchild->d_inode == inode);
884                 GOTO(out_dput, rc = 0);
885         }
886         tmp = pre_smfs_dentry(NULL, inode, cowed_dir);
887         /* link() is semanticaly-wrong for S_IFDIR, so we set S_IFREG
888          * for linking and return real mode back then -bzzz */
889         mode = inode->i_mode;
890         inode->i_mode = S_IFREG;
891
892         rc = cowed_dir->d_inode->i_op->link(tmp, cowed_dir->d_inode, dchild);         
893
894         post_smfs_dentry(tmp);
895         if (rc) {
896                 CERROR("error linking cowed inode %s to COWED: rc = %d\n",
897                         idname, rc);
898         } 
899         inode->i_mode = mode;
900         if ((mode & S_IFMT) == S_IFDIR) {
901                 dchild->d_inode->i_nlink++;
902                 cowed_dir->d_inode->i_nlink++;
903                 mark_inode_dirty(cowed_dir->d_inode);
904                 mark_inode_dirty(dchild->d_inode);
905         }
906 out_dput:
907         up(&cowed_dir->d_inode->i_sem);
908         dput(dchild);
909 out_lock:       
910         RETURN(rc);
911 }
912 /*
913  * Make a copy of the data and plug a redirector in between if there
914  * is no redirector yet.
915  */
916 int snap_do_cow(struct inode *inode, struct dentry *dparent, int del)
917 {
918         struct fsfilt_operations *snapops = I2SNAPCOPS(inode);
919         struct snap snap;
920         struct inode *cache_ind = NULL;
921         ENTRY;
922
923         if (!snapops || !snapops->fs_create_indirect) 
924                 RETURN(-EINVAL);
925
926         snap_last(inode, &snap);
927         cache_ind = snapops->fs_create_indirect(I2CI(inode), snap.sn_index, 
928                                           snap.sn_gen, I2CI(dparent->d_inode), 
929                                           del);
930         if(cache_ind && IS_ERR(cache_ind)) {
931                 CERROR("Create ind inode %lu index %d gen %d del %d rc%lu\n",
932                         inode->i_ino, snap.sn_index, snap.sn_gen, del,
933                         PTR_ERR(cache_ind));
934                 RETURN(PTR_ERR(cache_ind));
935         }
936         if (cache_ind) {
937                 iput(cache_ind);
938                 if (!SMFS_DO_INODE_COWED(inode)) {
939                         /*insert the inode to cowed inode*/
940                         SMFS_SET_INODE_COWED(inode); 
941                         link_cowed_inode(inode); 
942                 }
943         }
944         RETURN(0);
945 }
946 /*Dir inode will do cow*/
947 int smfs_cow_create_pre(struct inode *dir, void *de, void *data1, void *data2)
948 {
949         struct dentry *dparent;
950         struct dentry *dentry = (struct dentry *)de;
951         int rc = 0;
952         ENTRY;
953
954         if (smfs_needs_cow(dir) != -1) {
955                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
956                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
957                 dparent = dentry->d_parent->d_parent;
958                 if ((rc = snap_do_cow(dir, dparent, 0))) {
959                         CERROR("Do cow error %d\n", rc);
960                         RETURN(-EINVAL);
961                 }
962         }
963         RETURN(rc);
964 }
965
966 int smfs_cow_setattr_pre(struct inode *dir, void *de, void *data1, void *data2)
967 {
968         struct dentry *dentry = (struct dentry *)de;
969         int rc = 0;
970         ENTRY;
971         if (smfs_needs_cow(dir) != -1) {
972                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
973                 if ((snap_do_cow(dir, dentry->d_parent, 0))) {
974                         CERROR("Do cow error\n");
975                         RETURN(-EINVAL);
976                 }
977         }
978         RETURN(rc);
979 }
980
981 int smfs_cow_link_pre(struct inode *dir, void *de, void *data1, void *data2)
982 {
983         struct dentry *dparent;
984         struct dentry *dentry = (struct dentry *)de;
985         int rc = 0;
986         ENTRY;
987  
988         if (smfs_needs_cow(dir) != -1) {
989                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
990                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
991                 dparent = dentry->d_parent->d_parent;
992                 if ((snap_do_cow(dir, dparent, 0))) {
993                         CERROR("Do cow error\n");
994                         RETURN(-EINVAL);
995                 }
996                 if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 0))) {
997                         CERROR("Do cow error\n");
998                         RETURN(-EINVAL);
999                 }
1000         }
1001         RETURN(rc);
1002 }
1003
1004 int smfs_cow_unlink_pre(struct inode *dir, void *de, void *data1, void *data2)
1005 {
1006         struct dentry *dentry = (struct dentry *)de; 
1007         struct dentry *dparent;
1008         int rc = 0;
1009         ENTRY;
1010
1011         if (smfs_needs_cow(dir) != -1) {
1012                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
1013                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
1014                 dparent = dentry->d_parent->d_parent;
1015                 if ((snap_do_cow(dir, dparent, 0))) {
1016                         CERROR("Do cow error\n");
1017                         RETURN(-EINVAL);
1018                 }
1019                 if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 1))) {
1020                         CERROR("Do cow error\n");
1021                         RETURN(-EINVAL);
1022                 }
1023         
1024         }
1025         RETURN(rc);
1026 }
1027
1028 int smfs_cow_rename_pre(struct inode *dir, void *de, void *data1, void *data2)
1029 {
1030         struct dentry *dentry = (struct dentry*)de;
1031         struct inode *new_dir = (struct inode *)data1;
1032         struct dentry *new_dentry = (struct dentry *)data2;
1033         struct dentry *dparent;
1034         int rc = 0;
1035         ENTRY;
1036        
1037         LASSERT(new_dir);
1038         LASSERT(new_dentry); 
1039         if (smfs_needs_cow(dir) != -1) {
1040                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n", dir->i_ino);
1041                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
1042                 dparent = dentry->d_parent->d_parent;
1043                 if ((snap_do_cow(dir, dparent, 0))) {
1044                         CERROR("Do cow error\n");
1045                         RETURN(-EINVAL);
1046                 }
1047                 if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 0))) {
1048                         CERROR("Do cow error\n");
1049                         RETURN(-EINVAL);
1050                 }
1051         }
1052         if (smfs_needs_cow(new_dir) != -1) {
1053                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n", new_dir->i_ino);
1054                 LASSERT(new_dentry->d_parent && new_dentry->d_parent->d_parent);
1055                 dparent = new_dentry->d_parent->d_parent;
1056                 if ((new_dir != dir) && (snap_do_cow(new_dir, dparent, 0))){
1057                         CERROR("Do cow error\n");
1058                         RETURN(-EINVAL);
1059                 }
1060                 if (new_dentry->d_inode && new_dentry->d_inode->i_nlink == 1) {
1061                         if ((snap_do_cow(new_dentry->d_inode, 
1062                                          new_dentry->d_parent, 0))) {
1063                                 CERROR("Do cow error\n");
1064                                 RETURN(-EINVAL);
1065                         }
1066                 }
1067         } 
1068         RETURN(rc);
1069 }
1070
1071 int smfs_cow_write_pre(struct inode *inode, void *de, void *data1, void *data2)
1072 {
1073         struct dentry *dentry = (struct dentry*)de;
1074         struct snap_info *snap_info = NULL; 
1075         struct snap_table *table; 
1076         long   blocks[2]={-1,-1};
1077         int  index = 0, i, rc = 0;
1078         size_t count;
1079         loff_t pos;
1080
1081         ENTRY;
1082
1083         snap_info = smfs_find_snap_info(inode);
1084         if (!snap_info) {
1085                 CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
1086                 RETURN(0);                
1087         }
1088         table = snap_info->sni_table;
1089
1090         LASSERT(data1);
1091         LASSERT(data2);
1092         
1093         count = *(size_t *)data1;
1094         pos = *(loff_t*)data2;
1095  
1096         down(&inode->i_sem);
1097         
1098         if (smfs_needs_cow(inode) != -1 ) {
1099                 CDEBUG(D_INFO, "snap_needs_cow for ino %lu \n",inode->i_ino);
1100                 snap_do_cow(inode, dentry->d_parent, 0);
1101         }
1102         
1103         CDEBUG(D_INFO, "write offset %lld count %u \n", pos, count);
1104         
1105         if(pos & (PAGE_CACHE_SIZE - 1)){
1106                 blocks[0] = pos >> inode->i_sb->s_blocksize_bits;
1107         }
1108         pos += count - 1;
1109         if((pos + 1) & (PAGE_CACHE_SIZE - 1)){
1110                 blocks[1] = pos >> inode->i_sb->s_blocksize_bits;
1111         }
1112
1113         if (blocks[0] == blocks[1]) 
1114                 blocks[1] = -1;
1115         
1116         for (i = 0; i < 2; i++) {
1117                 int slot = 0;
1118                 if (blocks[i] == -1) 
1119                         continue;
1120                 /*Find the nearest page in snaptable and copy back it*/
1121                 for (slot = table->sntbl_count - 1; slot >= 0; slot--) {
1122                         struct fsfilt_operations *sops = I2SNAPCOPS(inode);
1123                         struct inode *cind = NULL;
1124                         int result = 0;
1125
1126                         index = table->sntbl_items[slot].sn_index;
1127                         cind = sops->fs_get_indirect(I2CI(inode), NULL, index);
1128                         if (!cind)  continue;
1129
1130                         CDEBUG(D_INFO, "find cache_ino %lu\n", cind->i_ino);
1131                 
1132                         result = sops->fs_copy_block(I2CI(inode), cind, 
1133                                                      blocks[i]);
1134                         if (result == 1) {
1135                                 iput(cind);
1136                                 result = 0;
1137                                 break;
1138                         }
1139                         if (result < 0) {
1140                                 iput(cind);
1141                                 up(&inode->i_sem);
1142                                 GOTO(exit, rc = result);
1143                         }
1144                         iput(cind);
1145                 }
1146         }
1147 exit:
1148         up(&inode->i_sem); 
1149         RETURN(rc);
1150 }
1151 EXPORT_SYMBOL(smfs_cow_write_pre);
1152 /*lookup inode in dotsnap inode */
1153 static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry,
1154                                struct snap_info *snap_info)
1155
1156         if (dentry->d_name.len == 1 && 
1157             !strcmp(dentry->d_name.name, ".")) {
1158                 d_add(dentry, iget(dir->i_sb, dir->i_ino));
1159         } else if (dentry->d_name.len == 2 && 
1160                    !strcmp(dentry->d_name.name, "..")) {
1161                 struct inode *inode;
1162                 struct dentry *dparent = dentry->d_parent;                                                                                                                                                                                       
1163                 if (dparent->d_inode) {
1164                         inode = iget(dir->i_sb, dparent->d_inode->i_ino);
1165                         if (inode) {
1166                                 if (!is_bad_inode(inode))
1167                                         d_add(dentry, inode);
1168                                 else
1169                                         iput(inode);
1170                         }
1171                 }
1172         } else {
1173                 /*find the name from the snaptable*/
1174                 struct fsfilt_operations *sops = I2SNAPCOPS(dir);
1175                 struct snap_table *table; 
1176                 struct inode *inode;
1177                 ino_t  cino;
1178                 int i = 0, index = -1;
1179
1180                 table = snap_info->sni_table;
1181                 
1182                 for (i = 0; i < table->sntbl_count; i++) {
1183                         char *name = table->sntbl_items[i].sn_name;
1184                         if ((dentry->d_name.len == strlen(name)) &&
1185                             (memcmp(dentry->d_name.name, name,
1186                                     dentry->d_name.len) == 0)) {
1187                                 index = table->sntbl_items[i].sn_index;
1188                                 break;
1189                         }
1190                 }
1191                 if (index == -1) {
1192                        CERROR("No such %s in this .snap dir \n", 
1193                                dentry->d_name.name);
1194                        RETURN(-ENOENT);
1195                 }
1196                 cino = sops->fs_get_indirect_ino(S2CSB(dir->i_sb), dir->i_ino,
1197                                                  index);
1198                 if (cino == 0)
1199                         cino = dir->i_ino;
1200                 inode = smfs_get_inode(dir->i_sb, cino, dir, index);
1201                 if (!inode || is_bad_inode(inode)) {
1202                         CERROR("Can not find cino %lu inode\n", cino);
1203                         RETURN(-ENOENT); 
1204                 } 
1205                 smfs_init_snap_inode_info(inode, dir, index);
1206                 d_add(dentry, inode);
1207         } 
1208         RETURN(0);
1209 }
1210 int smfs_cow_lookup_pre(struct inode *inode, void *de, void *data1,
1211                         void *data2)
1212 {
1213         struct dentry *dentry = (struct dentry*)de;
1214         struct snap_info *snap_info;
1215         struct snap_dot_info *dot_info;
1216         int rc = 0;
1217         ENTRY;
1218
1219         snap_info = smfs_find_snap_info(inode);
1220         if (!snap_info) {
1221                 CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
1222                 RETURN(0);                
1223         }
1224         
1225         dot_info = snap_info->sni_dot_info;
1226
1227         if (smfs_primary_inode(inode) && 
1228             dentry->d_name.len == dot_info->dot_name_len &&
1229             memcmp(dentry->d_name.name, dot_info->dot_name, 
1230                    strlen(dot_info->dot_name)) == 0) {
1231                 struct inode *dot_inode = NULL; 
1232                 
1233                 dot_inode = smfs_get_inode(inode->i_sb, inode->i_ino, inode,
1234                                            DOT_SNAP_INDEX);
1235                 smfs_init_snap_inode_info(dot_inode, inode, DOT_SNAP_INDEX);
1236                 d_add(dentry, dot_inode);
1237                 rc = 1;
1238                 RETURN(rc);
1239         } else if (smfs_dotsnap_inode(inode)) {
1240                 rc = smfs_dotsnap_lookup(inode, dentry, snap_info);
1241                 if (rc == 0)
1242                         rc = 1;
1243                 RETURN(rc);                
1244         } else {
1245                 /*HERE: will replace ino in dentry->d_name according to index,
1246                  *For iopen, will fix it in integrating snapfs to Lustre*/ 
1247 #if 0
1248                 struct fsfilt_operations *snapops = I2SNAPOPS(inode);
1249                 char *name = (char *)dentry->d_name.name;
1250                 unsigned long ino, hash, ind_ino; 
1251                 int len = sizeof(ind_ino);
1252                  
1253                 ino = simple_strtoul(name, 0, 0);         
1254
1255                 ind_ino = snapops->fs_get_indirect_ino(inode->i_sb, ino, index);
1256                 
1257                 snprintf(name, strlen(name), "0x%lx", ind_ino);                 
1258                 
1259                 hash = init_name_hash();
1260                 while (len--) {
1261                         unsigned char c; 
1262                         c = *(const unsigned char *)name++;
1263                         if (c == '\0') break;
1264                         hash = partial_name_hash(c, hash);
1265                 }
1266                 dentry->d_name.hash = end_name_hash(hash);
1267 #endif     
1268         }
1269         RETURN(rc);         
1270 }
1271
1272 struct inode *smfs_cow_get_ind(struct inode *inode, int index)
1273 {
1274         long block=(index << PAGE_CACHE_SHIFT) >> inode->i_sb->s_blocksize_bits;
1275         struct fsfilt_operations *sops = I2SNAPCOPS(inode); 
1276         struct snap_info *snap_info = NULL;
1277         struct snap_table *table = NULL;
1278         int slot;
1279
1280         ENTRY;
1281         
1282         snap_info = smfs_find_snap_info(inode);
1283         if (!snap_info) {
1284                 CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
1285                 RETURN(NULL);                
1286         }
1287         
1288         table = snap_info->sni_table;        
1289
1290         for (slot = table->sntbl_count - 1; slot >= 0; slot--) {
1291                 struct address_space_operations *aops = inode->i_mapping->a_ops;
1292                 struct inode *cache_inode = NULL;
1293                 int index = 0;
1294
1295                 index = table->sntbl_items[slot].sn_index;
1296                 cache_inode = sops->fs_get_indirect(I2CI(inode), NULL, index);
1297                                                                                                                                                                                                      
1298                 if (!cache_inode )  continue;
1299                 
1300                 if (aops->bmap(cache_inode->i_mapping, block))
1301                        RETURN(cache_inode); 
1302                 iput(cache_inode);
1303         }
1304
1305         RETURN(NULL);
1306 }
1307 EXPORT_SYMBOL(smfs_cow_get_ind);
1308
1309 static int smfs_cow_readdir_pre(struct inode *dir, void *de, void *data1,
1310                                 void *data2)
1311 {
1312         struct file *filp = (struct file*)de;
1313         void *dirent = data1; 
1314         filldir_t filldir = (filldir_t)data2;
1315         struct snap_info *snap_info = NULL;
1316         
1317         if (smfs_under_dotsnap_inode(dir))
1318                 RETURN(0);
1319
1320         snap_info = smfs_find_snap_info(dir);
1321
1322         if (!snap_info) {
1323                 CDEBUG(D_INFO, "can not find snap info for ino %lu\n", 
1324                        dir->i_ino);
1325                 RETURN(-EINVAL);                
1326         }
1327
1328         if (smfs_primary_inode(dir)) {
1329                 if (filp->f_pos == 0) {
1330                         struct snap_dot_info *dot = snap_info->sni_dot_info;
1331                         if (filldir(dirent, dot->dot_name, dot->dot_name_len, 
1332                                     filp->f_pos, -1, 0)) { 
1333                                 CERROR("fill .snap error \n");
1334                                 RETURN(-EINVAL);
1335                         }
1336                 } else {
1337                         filp->f_pos -= 1;
1338                 }
1339         } else if (smfs_dotsnap_inode(dir)) {
1340                 struct snap_table *table = snap_info->sni_table;   
1341                 int i = 0;
1342
1343                 if (filp->f_pos < 0)
1344                        RETURN(-EINVAL);
1345         
1346                 if ((filp->f_pos == 0) && filldir(dirent, ".", 1, 
1347                                                   filp->f_pos++, 
1348                                                   dir->i_ino, 0) < 0)
1349                        RETURN(-EIO);
1350                 if ((filp->f_pos == 1) && filldir(dirent, "..", 2, 
1351                                                   filp->f_pos++, 
1352                                                   dir->i_ino, 0) < 0)
1353                        RETURN(-EIO); 
1354                
1355                 for (i = filp->f_pos - 2; i < table->sntbl_count; i++, 
1356                      filp->f_pos++) { 
1357                         int slot = table->sntbl_count - i - 1;
1358                         
1359                         if (filldir(dirent, table->sntbl_items[slot].sn_name,
1360                                     strlen(table->sntbl_items[slot].sn_name),
1361                                     filp->f_pos, dir->i_ino, 0))
1362                                 break;
1363                          
1364                 } 
1365                 RETURN(1); 
1366         }
1367         
1368         RETURN(0); 
1369 }
1370
1371
1372 typedef int (*cow_funcs)(struct inode *dir, void *dentry, void *new_dir, 
1373                          void *new_dentry);
1374
1375 static cow_funcs smfs_cow_pre_funcs[HOOK_MAX + 1] = {
1376         [HOOK_CREATE]   smfs_cow_create_pre,
1377         [HOOK_LOOKUP]   smfs_cow_lookup_pre,
1378         [HOOK_LINK]     smfs_cow_link_pre,
1379         [HOOK_UNLINK]   smfs_cow_unlink_pre,
1380         [HOOK_SYMLINK]  smfs_cow_create_pre,
1381         [HOOK_MKDIR]    smfs_cow_create_pre,
1382         [HOOK_RMDIR]    smfs_cow_unlink_pre, 
1383         [HOOK_MKNOD]    smfs_cow_create_pre,
1384         [HOOK_RENAME]   smfs_cow_rename_pre,
1385         [HOOK_SETATTR]  smfs_cow_setattr_pre,
1386         [HOOK_WRITE]    smfs_cow_write_pre,
1387         [HOOK_READDIR]  smfs_cow_readdir_pre,
1388 };
1389
1390 static int smfs_revalidate_dotsnap_dentry(struct dentry *dentry, 
1391                                           struct inode *dir, int index)
1392 {
1393         struct inode *inode = dentry->d_inode;
1394         ENTRY;       
1395  
1396         if (!inode)
1397                 RETURN(0);
1398
1399         if (index > 0 && index != DOT_SNAP_INDEX) {
1400                 struct fsfilt_operations *sops = I2SNAPCOPS(inode); 
1401                 struct inode *cache_ind = NULL;
1402
1403                 cache_ind = sops->fs_get_indirect(I2CI(inode), NULL, index);
1404                 
1405                 if (cache_ind) {
1406                         struct inode *ind_inode = NULL;
1407
1408                         LASSERT(cache_ind->i_ino != I2CI(inode)->i_ino);
1409                         
1410                         ind_inode = smfs_get_inode(inode->i_sb, cache_ind->i_ino,
1411                                                    dir, index);
1412                         list_del_init(&dentry->d_alias);
1413                         iput(inode);
1414                         d_instantiate(dentry, ind_inode);                         
1415                         iput(cache_ind); 
1416                 }
1417         }
1418         RETURN(0);
1419 }
1420
1421 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1422 static int
1423 smfs_revalidate_nd(struct dentry *de, struct nameidata *nd)
1424 {
1425         struct inode *inode = de->d_inode;
1426         ENTRY;
1427
1428         if (!inode)
1429                 RETURN(0);
1430         
1431         if (smfs_under_dotsnap_inode(inode)) {
1432                 struct inode *dir = de->d_parent->d_inode;
1433                 int index = I2SNAPI(inode)->sn_index;
1434                 
1435                 smfs_revalidate_dotsnap_dentry(de, dir, index);
1436                 smfs_init_snap_inode_info(de->d_inode, dir, index);
1437         }
1438
1439         RETURN(0);
1440 }
1441 #else
1442 static int
1443 smfs_revalidate_it(struct dentry *de, int flags,
1444                    struct nameidata *nd,
1445                    struct lookup_intent *it)
1446 {
1447         struct inode *inode = de->d_inode;
1448         ENTRY;
1449
1450         if (!inode)
1451                 RETURN(0);
1452         
1453         if (smfs_under_dotsnap_inode(inode)) {
1454                 struct inode *dir = de->d_parent->d_inode;
1455                 int index = I2SNAPI(inode)->sn_index;
1456                 
1457                 smfs_revalidate_dotsnap_dentry(de, dir, index);
1458                 smfs_init_snap_inode_info(de->d_inode, dir, index);
1459         }
1460
1461         RETURN(0);
1462 }
1463 #endif
1464
1465 static int smfs_delete_dentry(struct dentry *dentry)
1466 {
1467         dentry->d_op = NULL; 
1468         return 0;
1469 }
1470  
1471 struct dentry_operations smfs_cow_dops = {
1472 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1473         .d_revalidate = smfs_revalidate_nd,
1474 #else
1475         .d_revalidate_it = smfs_revalidate_it,
1476 #endif
1477         .d_delete     = smfs_delete_dentry,
1478 };
1479
1480 int smfs_cow_lookup_post(struct inode *dir, void *de, void *data1,
1481                          void *data2)
1482 {
1483         struct dentry *dentry = (struct dentry*)de;
1484         struct inode *inode = dentry->d_inode; 
1485         ENTRY;
1486
1487         if (inode && smfs_under_dotsnap_inode(inode)) {
1488                 int index = I2SNAPI(dir)->sn_index;
1489         
1490                 smfs_revalidate_dotsnap_dentry(dentry, dir, index);
1491                 smfs_init_snap_inode_info(inode, dir, index);
1492         }
1493         dentry->d_op = &smfs_cow_dops;  
1494         RETURN(0);
1495 }
1496
1497 static int smfs_cow_readdir_post(struct inode *dir, void *de, void *data1,
1498                                  void *data2)
1499 {
1500         struct file *filp = (struct file*)de;
1501         
1502         if (smfs_primary_inode(dir)) {
1503                 filp->f_pos += 1;
1504         }
1505         RETURN(0); 
1506 }
1507
1508
1509 static cow_funcs smfs_cow_post_funcs[HOOK_MAX + 1] = {
1510         [HOOK_CREATE]   NULL,
1511         [HOOK_LOOKUP]   smfs_cow_lookup_post,
1512         [HOOK_LINK]     NULL,
1513         [HOOK_UNLINK]   NULL,
1514         [HOOK_SYMLINK]  NULL,
1515         [HOOK_MKDIR]    NULL,
1516         [HOOK_RMDIR]    NULL, 
1517         [HOOK_MKNOD]    NULL,
1518         [HOOK_RENAME]   NULL,
1519         [HOOK_SETATTR]  NULL,
1520         [HOOK_WRITE]    NULL,
1521         [HOOK_READDIR]  smfs_cow_readdir_post,
1522 };
1523
1524 static int smfs_cow_pre(struct inode *dir, void *dentry, void *new_dir, 
1525                         void *new_dentry, int op)
1526 {
1527         if (smfs_cow_pre_funcs[op]) {
1528                 return smfs_cow_pre_funcs[op](dir, dentry, new_dir, new_dentry);
1529         }
1530         return 0;
1531 }
1532
1533 static int smfs_cow_post(struct inode *dir, void *dentry, void *new_dir, 
1534                          void *new_dentry, int op)
1535 {
1536         if (smfs_cow_post_funcs[op]) {
1537                 return smfs_cow_post_funcs[op](dir, dentry, new_dir, new_dentry);
1538         }
1539         return 0;
1540 }
1541