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