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