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