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