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                 } else {
317                         CERROR("Can not retrive the snaptable from this filesystem\n");
318                         GOTO(exit, rc);
319                 }
320         } else { 
321                 if (le32_to_cpu(snap_table->sntbl_magic) != SNAPTABLE_MAGIC) {
322                         CERROR("On disk snaptable is not right \n");
323                         GOTO(exit, rc = -EIO);
324                 }
325         }
326         init_MUTEX(&snap_info->sni_sema);
327         snap_info->sni_root_ino = de->d_inode->i_ino;
328         rc = smfs_init_cowed_dir(snap_info, de);
329         if (rc) {
330                 CERROR("Init cowed dir error rc=%d\n", rc);
331                 GOTO(exit, rc); 
332         }
333         rc = smfs_init_dotinfo(snap_info);
334 exit:
335         if (root_inode) 
336                 iput(root_inode);
337         if (rc && snap_table)
338                 OBD_FREE(snap_table, table_size);
339         RETURN(rc);
340 }
341
342 static struct snap_info *smfs_create_snap_info(struct smfs_super_info *sinfo, 
343                                                struct dentry *dentry)
344 {
345         struct snap_info *snap_info = NULL;
346         int rc = 0;
347         ENTRY;
348  
349         OBD_ALLOC(snap_info, sizeof(struct snap_info)); 
350         if (!snap_info) 
351                 RETURN(ERR_PTR(-ENOMEM));  
352         rc = smfs_init_snap_info(sinfo, snap_info, dentry);  
353         if (rc) 
354                 GOTO(exit, snap_info = ERR_PTR(rc));
355        
356         /*set cow flags for the snap root inode*/ 
357         I2SMI(dentry->d_inode)->smi_flags |= SM_DO_COW;
358         I2SNAPI(dentry->d_inode)->sn_root_ino = dentry->d_inode->i_ino; 
359 exit:
360         if (rc)
361                 OBD_FREE(snap_info, sizeof(struct snap_info));
362         RETURN(snap_info);
363 }
364
365 static int smfs_cow_pre(struct inode *dir, struct dentry *dentry, void *new_dir, 
366                         void *new_dentry, int op);
367
368 static int smfs_cow_post(struct inode *dir, struct dentry *dentry, void *new_dir, 
369                          void *new_dentry, int op);
370 #define COW_HOOK "cow_hook"
371 static int smfs_cow_pre_hook(struct inode *inode, struct dentry *dentry, 
372                              void *data1, void *data2, int op, void *handle)
373 {
374         int rc = 0;
375         ENTRY;
376  
377         if (smfs_do_cow(inode)) {
378                 /*FIXME:WANGDI, get index from the dentry*/
379                 #if 0
380                 int index = 0;
381                 smfs_get_dentry_name_index(dentry, &name, index);       
382                 smfs_free_dentry_name(&name);
383                 #endif
384                 rc = smfs_cow_pre(inode, dentry, data1, data2, op);           
385         }
386         RETURN(rc);                                                                     
387 }
388 static int smfs_cow_post_hook(struct inode *inode, struct dentry *dentry, 
389                               void *data1, void *data2, int op, void *handle)
390 {
391         int rc = 0;
392         ENTRY;
393  
394         if (smfs_do_cow(inode)) {
395                 rc = smfs_cow_post(inode, dentry, data1, data2, op);           
396         }
397         RETURN(rc);                                                                     
398 }
399
400 int smfs_cow_init(struct super_block *sb)
401 {
402         struct smfs_super_info *smfs_info = S2SMI(sb);
403         struct smfs_hook_ops *cow_hops = NULL;
404         struct fsfilt_operations *sops;
405         struct inode *root_inode = smfs_info->smsi_sb->s_root->d_inode; 
406         int snap_count = 0, rc = 0, vallen;
407
408         ENTRY;
409
410         SMFS_SET_COW(smfs_info);
411       
412         cow_hops = smfs_alloc_hook_ops(COW_HOOK, smfs_cow_pre_hook, 
413                                        smfs_cow_post_hook);
414         if (!cow_hops) {
415                 RETURN(-ENOMEM);
416         }
417  
418         rc = smfs_register_hook_ops(smfs_info, cow_hops);
419         if (rc) {
420                 smfs_free_hook_ops(cow_hops);
421                 RETURN(rc);
422         }
423         
424         rc = smfs_init_snap_super_info(smfs_info);
425         if (rc && cow_hops) {
426                 smfs_unregister_hook_ops(smfs_info, cow_hops->smh_name);
427                 smfs_free_hook_ops(cow_hops);
428                 RETURN(rc);
429         }
430         sops = smfs_info->smsi_snap_info->snap_cache_fsfilt; 
431         
432         vallen = sizeof(int); 
433         rc = sops->fs_get_snap_info(root_inode, SNAP_COUNT, strlen(SNAP_COUNT),
434                                     &snap_count, &vallen);
435         if (rc)
436                 GOTO(exit, rc);       
437  
438         if (snap_count > 0) {
439                 int snap_root_size = snap_count * sizeof(ino_t);
440                 ino_t *snap_root;
441                 int i;
442                 
443                 OBD_ALLOC(snap_root, snap_root_size);
444                 
445                 if (!snap_root)
446                         GOTO(exit, rc = -ENOMEM); 
447                 
448                 rc = sops->fs_get_snap_info(root_inode, SNAP_ROOT_INO, 
449                                             strlen(SNAP_ROOT_INO), snap_root, 
450                                             &snap_root_size);
451                 if (rc) {
452                         OBD_FREE(snap_root, sizeof(int) * snap_count);
453                         GOTO(exit, rc);
454                 }
455                 for (i = 0; i < snap_count; i++) {
456                         ino_t root_ino = le32_to_cpu(snap_root[i]);
457                         struct dentry *tmp = smfs_info->smsi_sb->s_root;
458                         struct snap_info *snap_info;                      
459                         struct dentry *dentry;                        
460  
461                         root_inode = smfs_get_inode(sb, root_ino, NULL, 0);
462                         smfs_init_snap_inode_info(root_inode, NULL, 0);
463                         dentry = pre_smfs_dentry(NULL, root_inode, tmp); 
464                         snap_info = smfs_create_snap_info(S2SMI(sb), dentry);
465                         post_smfs_dentry(dentry);
466                         if (IS_ERR(snap_info)) {
467                                 OBD_FREE(snap_root, sizeof(int) * snap_count);
468                                 GOTO(exit, rc = PTR_ERR(snap_info));
469                         }                
470                         list_add(&snap_info->sni_list, 
471                                  &(S2SNAPI(sb)->snap_list));        
472                 }
473         }       
474 exit:
475         if (rc) 
476                 smfs_cow_cleanup(smfs_info);
477         
478         RETURN(rc);
479 }
480
481 static int smfs_cleanup_dotinfo(struct snap_info *snap_info)
482 {       
483         struct snap_dot_info *dot_info = NULL;
484         int rc = 0;
485         ENTRY;
486
487         if (!snap_info->sni_dot_info)
488                 RETURN(rc);
489        
490         dot_info = snap_info->sni_dot_info;
491
492         if (dot_info->dot_name) { 
493                 OBD_FREE(dot_info->dot_name, dot_info->dot_name_len + 1);
494         }
495         
496         OBD_FREE(dot_info, sizeof(struct snap_dot_info));
497
498         RETURN(rc);
499 }
500
501 int smfs_cleanup_snap_info(struct snap_info *snap_info)
502 {
503         struct snap_table      *snap_table = snap_info->sni_table;
504         int rc = 0, table_size;
505         ENTRY;
506
507         l_dput(snap_info->sni_cowed_dentry);
508         if (snap_table) {
509                 table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count);
510                 OBD_FREE(snap_info->sni_table, table_size);
511         }
512         smfs_cleanup_dotinfo(snap_info);
513         RETURN(rc);
514 }
515
516 int smfs_cow_cleanup(struct smfs_super_info *smb)
517 {
518         struct snap_super_info   *snap_sinfo = smb->smsi_snap_info;
519         struct list_head         *snap_list = &snap_sinfo->snap_list; 
520         struct smfs_hook_ops     *cow_hops;
521         int                      rc = 0; 
522         ENTRY;
523
524         while (!list_empty(snap_list)) {
525                 struct snap_info *snap_info;
526                 
527                 snap_info = list_entry(snap_list->next, struct snap_info,
528                                        sni_list); 
529                 rc = smfs_cleanup_snap_info(snap_info); 
530                 if (rc) 
531                         CERROR("cleanup snap_info error rc=%d\n", rc);
532                 list_del(&snap_info->sni_list); 
533                 OBD_FREE(snap_info, sizeof(struct snap_info));
534         } 
535          
536         if (snap_sinfo->snap_fsfilt) 
537                 fsfilt_put_ops(snap_sinfo->snap_fsfilt);
538         if (snap_sinfo->snap_cache_fsfilt)
539                 fsfilt_put_ops(snap_sinfo->snap_cache_fsfilt);
540
541         cow_hops = smfs_unregister_hook_ops(smb, COW_HOOK);
542         smfs_free_hook_ops(cow_hops);
543
544         SMFS_CLEAN_COW(smb);
545         if (snap_sinfo) 
546                OBD_FREE(snap_sinfo, sizeof(struct snap_super_info));
547         RETURN(rc);
548 }
549
550 int smfs_snap_test_inode(struct inode *inode, void *args)
551
552         struct smfs_iget_args *sargs = (struct smfs_iget_args*)args;
553         struct inode *dir;
554
555         LASSERT(sargs);
556         
557         dir = sargs->s_inode;
558         
559         if (sargs->s_index > 0) { 
560                 if (I2SNAPI(inode)->sn_index != sargs->s_index)
561                         return 0;
562         }else {
563                 if (dir && I2SNAPI(inode)->sn_index != I2SNAPI(dir)->sn_index)
564                         return 0;
565         }
566         return 1;
567 }
568 /* latest snap: returns 
569    -  the index of the latest snapshot before NOW
570    -  hence it returns 0 in case all the volume snapshots lie in the future
571    -  this is the index where a COW will land (will be created) 
572 */
573 void snap_last(struct inode *inode, struct snap *snap)
574 {
575         time_t now = LTIME_S(CURRENT_TIME);
576         struct snap_table *snap_table;
577         struct snap_info  *snap_info;
578         int i ;
579
580         ENTRY;
581
582         snap_info = smfs_find_snap_info(inode);
583         if (!snap_info) {
584                 CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
585                 EXIT;
586                 return;
587         }
588         snap_table = snap_info->sni_table;
589         /* start at the highest index in the superblock snaptime array */ 
590         if (snap_table->sntbl_count == 0) {
591                memset(snap, 0, sizeof(struct snap)); 
592         } else {
593                 i = snap_table->sntbl_count - 1;
594                 snap->sn_index = snap_table->sntbl_items[i].sn_index;
595                 snap->sn_time = snap_table->sntbl_items[i].sn_time;
596                 snap->sn_gen = snap_table->sntbl_items[i].sn_gen;
597         }
598         CDEBUG(D_INFO, "index: %d, time[i]: %ld, now: %ld\n",
599                snap->sn_index, snap->sn_time, now);
600         EXIT;
601         return;
602 }
603
604 static inline int get_index_of_item(struct snap_table *table, char *name)
605 {
606         int count = table->sntbl_count;
607         int i, j;
608         ENTRY;
609         
610         for (i = 0; i < table->sntbl_max_count; i++) { 
611                 if (!strcmp(name, table->sntbl_items[i].sn_name)) {
612                         CERROR("Duplicate name %s in snaptable\n", name); 
613                         RETURN(-EINVAL);
614                 }       
615         }
616
617         for (i = 0; i < table->sntbl_max_count; i++) {
618                 int found = 0;
619                 for (j = 0; j < (count + 1); j++) {
620                         if (table->sntbl_items[j].sn_index == i) {
621                                 found = 1;
622                                 break;  
623                         }
624                 }
625                 if (!found)
626                         RETURN(i);
627         }
628         CERROR("snaptable Full\n");
629         RETURN(-ENOSPC);
630 }
631
632 static struct dentry *smfs_find_snap_root(struct super_block *sb, 
633                                           char *path_name)
634 {
635         struct dentry *dentry = NULL;
636         struct nameidata nd;
637         ENTRY;
638
639 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
640         if (path_init(path_name, LOOKUP_FOLLOW, &nd)) {
641                 error = path_walk(path_name, &nd);
642                 if (error) {
643                         path_release(&nd);
644                         RETURN(NULL);
645                 }
646         } else {
647                 RETURN(NULL);
648         }
649 #else
650         if (path_lookup(path_name, LOOKUP_FOLLOW, &nd))
651                 RETURN(NULL);
652                                                                                                                                                                                                      
653 #endif
654         dentry = dget(nd.dentry); 
655         path_release(&nd);
656         RETURN(dentry); 
657 }
658 static int snap_add_item(struct smfs_super_info *smb, 
659                          struct snap_info *snap_info,
660                          char *name)
661 {        
662         struct fsfilt_operations *snapops;
663         struct snap_table        *snap_table = snap_info->sni_table;
664         struct inode             *root_inode = NULL;
665         int                      table_size, count = 0, index = 0, rc = 0;
666         struct  snap             *snap_item;
667         ENTRY;
668
669         count = snap_table->sntbl_count; 
670         root_inode = iget(smb->smsi_sb, snap_info->sni_root_ino);
671         if (!root_inode || is_bad_inode(root_inode)) 
672                 RETURN(-EIO); 
673         /* XXX Is down this sema necessary*/
674         down_interruptible(&snap_info->sni_sema);
675         snap_item = &snap_table->sntbl_items[count];
676         snapops = smb->smsi_snap_info->snap_cache_fsfilt;
677         /*add item in snap_table set generation*/
678         snap_item->sn_time = LTIME_S(CURRENT_TIME);
679         /* find table index */
680         index = get_index_of_item(snap_table, name);
681         if (index < 0) 
682                 GOTO(exit, rc = index);
683         
684         snap_item->sn_index = index;
685         snap_item->sn_flags = 0;
686         snap_item->sn_gen = snap_table->sntbl_generation + 1; 
687         memcpy(snap_item->sn_name, name, SNAP_MAX_NAMELEN);
688         /* Wrote the whole snap_table to disk */
689         table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count); 
690          
691         rc = snapops->fs_set_snap_info(root_inode, SNAPTABLE_INFO, 
692                                        strlen(SNAPTABLE_INFO),
693                                        snap_table, &table_size);
694         if (rc) {
695                 CERROR("Set snaptable error rc=%d\n", rc);
696                 GOTO(exit, rc);
697         }
698         snap_table->sntbl_count++;
699         snap_table->sntbl_generation++;
700 exit:
701         up(&snap_info->sni_sema);
702         if (root_inode)
703                 iput(root_inode);
704         RETURN(rc);
705 }
706
707 static struct snap_info * smfs_find_create_snap_info(struct super_block *sb, 
708                                                      struct dentry *dentry) 
709 {       
710         struct snap_super_info   *snap_sinfo = S2SNAPI(sb);
711         struct snap_info *snap_info, *tmp;
712         ENTRY;
713         
714         list_for_each_entry_safe(snap_info, tmp, &snap_sinfo->snap_list, 
715                                  sni_list) {
716                 if (snap_info->sni_root_ino == dentry->d_inode->i_ino) {
717                         RETURN(snap_info);
718                 }      
719         } 
720
721         CDEBUG(D_INFO, "create a new  snap info root ino %lu\n", 
722                dentry->d_inode->i_ino);
723
724         snap_info = smfs_create_snap_info(S2SMI(sb), dentry);  
725
726         if (IS_ERR(snap_info))
727                 RETURN(snap_info);
728
729         list_add(&snap_info->sni_list, &snap_sinfo->snap_list);        
730         RETURN(snap_info);  
731 }         
732
733 int smfs_add_snap_item(struct super_block *sb, char *path_name, char *name)
734 {
735         struct dentry  *dentry = NULL;
736         struct snap_info *snap_info;
737         int            rc = 0;        
738         ENTRY;
739                 
740         if (!SMFS_DO_COW(S2SMI(sb))) {
741                 RETURN(0);
742         }
743
744         if (!path_name || !name) {
745                 CERROR("patch_name and snapshot_name is NULL");
746                 RETURN(-EINVAL);
747         } 
748         dentry = smfs_find_snap_root(sb, path_name);
749         if (IS_ERR(dentry)) {
750                 CERROR("can not find snap_shot root by %s\n", path_name);
751                 RETURN(PTR_ERR(dentry)); 
752         }
753         snap_info = smfs_find_create_snap_info(sb, dentry);
754         if (IS_ERR(snap_info)) {
755                 CERROR("can not find snap_info by %s rc=%lu\n", path_name,
756                         PTR_ERR(snap_info));
757                 GOTO(exit, rc = PTR_ERR(snap_info)); 
758         }
759
760         rc = snap_add_item(S2SMI(sb), snap_info, name);
761 exit:       
762         dput(dentry); 
763         RETURN(rc); 
764 }        
765 //EXPORT_SYMBOL(smfs_add_snap_item);
766 /*
767  * Note: this function should be differnet with snap_do_cow.
768  * In smfs_do_cow, we check the EA for whether do cow for that inode.
769  * In smfs_needs_cow, we check whether we do need to do cow. 
770  */
771 int smfs_needs_cow(struct inode *inode)
772 {
773         struct smfs_inode_info  *smi_info = I2SMI(inode); 
774         struct snap_inode_info *snap_info = NULL;
775         struct snap snap;
776         int index = -1;
777         ENTRY;
778
779         snap_info = &(smi_info->sm_sninfo);
780         
781         snap_last(inode, &snap);
782         /* decision .... if the snapshot is more recent than the object,
783          * then any change to the object should cause a COW.
784          */
785         if (snap_info->sn_gen < snap.sn_gen ) 
786                 index = snap.sn_index;
787
788         CDEBUG(D_INFO, "snap_needs_cow, ino %lu , get index %d\n",
789                inode->i_ino, index);
790
791         RETURN(index);
792 } /* snap_needs_cow */
793
794 static int link_cowed_inode(struct inode *inode)
795 {
796         struct dentry *cowed_dir = NULL;
797         char fidname[LL_FID_NAMELEN];
798         struct snap_info *snap_info;    
799         int fidlen = 0, rc = 0;
800         struct dentry *dchild = NULL;
801         struct dentry *tmp = NULL;
802         unsigned mode;
803
804         snap_info = smfs_find_snap_info(inode);
805         if (!snap_info) {
806                 CERROR("can not find snap info for inode %p\n", inode);
807                 RETURN(-EINVAL);                
808         }
809
810         cowed_dir = snap_info->sni_cowed_dentry;
811         
812         fidlen = ll_fid2str(fidname, inode->i_ino, inode->i_generation);
813
814         down(&cowed_dir->d_inode->i_sem);
815         dchild = ll_lookup_one_len(fidname, cowed_dir, fidlen);
816         if (IS_ERR(dchild)) {
817                 rc = PTR_ERR(dchild);
818                 if (rc != -EPERM && rc != -EACCES)
819                         CERROR("child lookup error %d\n", rc);
820                 GOTO(out_lock, rc);
821         }
822         if (dchild->d_inode != NULL) {
823                 CERROR("re-cowed file %s?\n", dchild->d_name.name);
824                 LASSERT(dchild->d_inode == inode);
825                 GOTO(out_dput, rc = 0);
826         }
827         tmp = pre_smfs_dentry(NULL, inode, cowed_dir);
828         /* link() is semanticaly-wrong for S_IFDIR, so we set S_IFREG
829          * for linking and return real mode back then -bzzz */
830         mode = inode->i_mode;
831         inode->i_mode = S_IFREG;
832         rc = vfs_link(tmp, cowed_dir->d_inode, dchild);
833         post_smfs_dentry(tmp);
834         if (rc) {
835                 CERROR("error linking cowed inode %s to COWED: rc = %d\n",
836                         fidname, rc);
837         } 
838         inode->i_mode = mode;
839         if ((mode & S_IFMT) == S_IFDIR) {
840                 dchild->d_inode->i_nlink++;
841                 cowed_dir->d_inode->i_nlink++;
842         }
843         mark_inode_dirty(dchild->d_inode);
844 out_dput:
845         dput(dchild);
846 out_lock:       
847         up(&cowed_dir->d_inode->i_sem);
848         RETURN(rc);
849 }
850 /*
851  * Make a copy of the data and plug a redirector in between if there
852  * is no redirector yet.
853  */
854 int snap_do_cow(struct inode *inode, struct dentry *dparent, int del)
855 {
856         struct fsfilt_operations *snapops = I2SNAPCOPS(inode);
857         struct snap snap;
858         struct inode *cache_ind = NULL;
859         ENTRY;
860
861         if (!snapops || !snapops->fs_create_indirect) 
862                 RETURN(-EINVAL);
863
864         snap_last(inode, &snap);
865         cache_ind = snapops->fs_create_indirect(I2CI(inode), snap.sn_index, 
866                                           snap.sn_gen, I2CI(dparent->d_inode), 
867                                           del);
868         if(cache_ind && IS_ERR(cache_ind)) {
869                 CERROR("Create ind inode %lu index %d gen %d del %d rc%lu\n",
870                         inode->i_ino, snap.sn_index, snap.sn_gen, del,
871                         PTR_ERR(cache_ind));
872                 RETURN(PTR_ERR(cache_ind));
873         }
874         iput(cache_ind);
875         if (!SMFS_DO_INODE_COWED(inode)) {
876                 /*insert the inode to cowed inode*/
877                 SMFS_SET_INODE_COWED(inode); 
878                 link_cowed_inode(inode); 
879         }
880         RETURN(0);
881 }
882 /*Dir inode will do cow*/
883 int smfs_cow_create(struct inode *dir, struct dentry *dentry,
884                     void *data1, void *data2)
885 {
886         int rc = 0;
887         struct dentry *dparent;
888         ENTRY;
889
890         if (smfs_needs_cow(dir) != -1) {
891                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
892                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
893                 dparent = dentry->d_parent->d_parent;
894                 if ((rc = snap_do_cow(dir, dparent, 0))) {
895                         CERROR("Do cow error %d\n", rc);
896                         RETURN(-EINVAL);
897                 }
898         }
899         RETURN(rc);
900 }
901
902 int smfs_cow_setattr(struct inode *dir, struct dentry *dentry,
903                      void *data1, void *data2)
904 {
905         int rc = 0;
906         ENTRY;
907         if (smfs_needs_cow(dir) != -1) {
908                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
909                 if ((snap_do_cow(dir, dentry->d_parent, 0))) {
910                         CERROR("Do cow error\n");
911                         RETURN(-EINVAL);
912                 }
913         }
914         RETURN(rc);
915 }
916
917 int smfs_cow_link(struct inode *dir, struct dentry *dentry,
918                   void *data1, void *data2)
919 {
920         int rc = 0;
921         struct dentry *dparent;
922         ENTRY;
923  
924         if (smfs_needs_cow(dir) != -1) {
925                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
926                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
927                 dparent = dentry->d_parent->d_parent;
928                 if ((snap_do_cow(dir, dparent, 0))) {
929                         CERROR("Do cow error\n");
930                         RETURN(-EINVAL);
931                 }
932                 if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 0))) {
933                         CERROR("Do cow error\n");
934                         RETURN(-EINVAL);
935                 }
936         }
937         RETURN(rc);
938 }
939
940 int smfs_cow_unlink(struct inode *dir, struct dentry *dentry,
941                     void *data1, void *data2)
942 {
943         struct dentry *dparent;
944         int rc = 0;
945         ENTRY;
946
947         if (smfs_needs_cow(dir) != -1) {
948                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
949                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
950                 dparent = dentry->d_parent->d_parent;
951                 if ((snap_do_cow(dir, dparent, 0))) {
952                         CERROR("Do cow error\n");
953                         RETURN(-EINVAL);
954                 }
955                 if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 1))) {
956                         CERROR("Do cow error\n");
957                         RETURN(-EINVAL);
958                 }
959         
960         }
961         RETURN(rc);
962 }
963
964 int smfs_cow_rename(struct inode *dir, struct dentry *dentry, 
965                     void *data1, void *data2)
966 {
967         struct inode *new_dir = (struct inode *)data1;
968         struct dentry *new_dentry = (struct dentry *)data2;
969         struct dentry *dparent;
970         int rc = 0;
971         ENTRY;
972        
973         LASSERT(new_dir);
974         LASSERT(new_dentry); 
975         if (smfs_needs_cow(dir) != -1) {
976                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n", dir->i_ino);
977                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
978                 dparent = dentry->d_parent->d_parent;
979                 if ((snap_do_cow(dir, dparent, 0))) {
980                         CERROR("Do cow error\n");
981                         RETURN(-EINVAL);
982                 }
983                 if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 0))) {
984                         CERROR("Do cow error\n");
985                         RETURN(-EINVAL);
986                 }
987         }
988         if (smfs_needs_cow(new_dir) != -1) {
989                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n", new_dir->i_ino);
990                 LASSERT(new_dentry->d_parent && new_dentry->d_parent->d_parent);
991                 dparent = new_dentry->d_parent->d_parent;
992                 if ((new_dir != dir) && (snap_do_cow(new_dir, dparent, 0))){
993                         CERROR("Do cow error\n");
994                         RETURN(-EINVAL);
995                 }
996                 if (new_dentry->d_inode && new_dentry->d_inode->i_nlink == 1) {
997                         if ((snap_do_cow(new_dentry->d_inode, 
998                                          new_dentry->d_parent, 0))) {
999                                 CERROR("Do cow error\n");
1000                                 RETURN(-EINVAL);
1001                         }
1002                 }
1003         } 
1004         RETURN(rc);
1005 }
1006
1007 int smfs_cow_write(struct inode *inode, struct dentry *dentry, void *data1,
1008                    void *data2)
1009 {
1010         struct snap_info *snap_info = NULL; 
1011         struct snap_table *table; 
1012         long   blocks[2]={-1,-1};
1013         int  index = 0, i, rc = 0;
1014         size_t count;
1015         loff_t pos;
1016
1017         ENTRY;
1018
1019         snap_info = smfs_find_snap_info(inode);
1020         if (!snap_info) {
1021                 CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
1022                 RETURN(0);                
1023         }
1024         table = snap_info->sni_table;
1025
1026         LASSERT(data1);
1027         LASSERT(data2);
1028         
1029         count = *(size_t *)data1;
1030         pos = *(loff_t*)data2;
1031  
1032         down(&inode->i_sem);
1033         
1034         if (smfs_needs_cow(inode) != -1 ) {
1035                 CDEBUG(D_INFO, "snap_needs_cow for ino %lu \n",inode->i_ino);
1036                 snap_do_cow(inode, dentry->d_parent, 0);
1037         }
1038         
1039         CDEBUG(D_INFO, "write offset %lld count %u \n", pos, count);
1040         
1041         if(pos & (PAGE_CACHE_SIZE - 1)){
1042                 blocks[0] = pos >> inode->i_sb->s_blocksize_bits;
1043         }
1044         pos += count - 1;
1045         if((pos + 1) & (PAGE_CACHE_SIZE - 1)){
1046                 blocks[1] = pos >> inode->i_sb->s_blocksize_bits;
1047         }
1048
1049         if (blocks[0] == blocks[1]) 
1050                 blocks[1] = -1;
1051         
1052         for (i = 0; i < 2; i++) {
1053                 int slot = 0;
1054                 if (blocks[i] == -1) 
1055                         continue;
1056                 /*Find the nearest page in snaptable and copy back it*/
1057                 for (slot = table->sntbl_count - 1; slot >= 0; slot--) {
1058                         struct fsfilt_operations *sops = I2SNAPCOPS(inode);
1059                         struct inode *cind = NULL;
1060                         int result = 0;
1061
1062                         index = table->sntbl_items[slot].sn_index;
1063                         cind = sops->fs_get_indirect(I2CI(inode), NULL, index);
1064                         if (!cind)  continue;
1065
1066                         CDEBUG(D_INFO, "find cache_ino %lu\n", cind->i_ino);
1067                 
1068                         result = sops->fs_copy_block(I2CI(inode), cind, 
1069                                                      blocks[i]);
1070                         if (result == 1) {
1071                                 iput(cind);
1072                                 result = 0;
1073                                 break;
1074                         }
1075                         if (result < 0) {
1076                                 iput(cind);
1077                                 up(&inode->i_sem);
1078                                 GOTO(exit, rc = result);
1079                         }
1080                         iput(cind);
1081                 }
1082         }
1083 exit:
1084         up(&inode->i_sem); 
1085         RETURN(rc);
1086 }
1087 EXPORT_SYMBOL(smfs_cow_write);
1088 /*lookup inode in dotsnap inode */
1089 static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry,
1090                                struct snap_info *snap_info)
1091
1092         if (dentry->d_name.len == 1 && 
1093             !strcmp(dentry->d_name.name, ".")) {
1094                 d_add(dentry, iget(dir->i_sb, dir->i_ino));
1095         } else if (dentry->d_name.len == 2 && 
1096                    !strcmp(dentry->d_name.name, "..")) {
1097                 struct inode *inode;
1098                 struct dentry *dparent = dentry->d_parent;                                                                                                                                                                                       
1099                 if (dparent->d_inode) {
1100                         inode = iget(dir->i_sb, dparent->d_inode->i_ino);
1101                         if (inode) {
1102                                 if (!is_bad_inode(inode))
1103                                         d_add(dentry, inode);
1104                                 else
1105                                         iput(inode);
1106                         }
1107                 }
1108         } else {
1109                 /*find the name from the snaptable*/
1110                 struct fsfilt_operations *sops = I2SNAPCOPS(dir);
1111                 struct snap_table *table; 
1112                 struct inode *inode;
1113                 ino_t  cino;
1114                 int i = 0, index = -1;
1115
1116                 table = snap_info->sni_table;
1117                 
1118                 for (i = 0; i < table->sntbl_count; i++) {
1119                         char *name = table->sntbl_items[i].sn_name;
1120                         if ((dentry->d_name.len == strlen(name)) &&
1121                             (memcmp(dentry->d_name.name, name,
1122                                     dentry->d_name.len) == 0)) {
1123                                 index = table->sntbl_items[i].sn_index;
1124                                 break;
1125                         }
1126                 }
1127                 if (index != -1) {
1128                        CERROR("No such %s in this .snap dir \n", 
1129                                dentry->d_name.name);
1130                        RETURN(-ENOENT);
1131                 }
1132                 cino = sops->fs_get_indirect_ino(S2CSB(dir->i_sb), dir->i_ino,
1133                                                  index);
1134                 inode = smfs_get_inode(dir->i_sb, cino, dir, index);
1135                 if (!inode || is_bad_inode(inode)) {
1136                         CERROR("Can not find cino %lu inode\n", cino);
1137                         RETURN(-ENOENT); 
1138                 } 
1139                 smfs_init_snap_inode_info(inode, dir, index);
1140                 d_add(dentry, inode);
1141         } 
1142         RETURN(0);
1143 }
1144 int smfs_cow_lookup(struct inode *inode, struct dentry *dentry, void *data1,
1145                     void *data2)
1146 {
1147         struct snap_info *snap_info;
1148         struct snap_dot_info *dot_info;
1149         int rc = 0, index = 0;
1150         ENTRY;
1151
1152         snap_info = smfs_find_snap_info(inode);
1153         if (!snap_info) {
1154                 CDEBUG(D_INFO, "can not find snap info for inode %p\n", inode);
1155                 RETURN(0);                
1156         }
1157         
1158         dot_info = snap_info->sni_dot_info;
1159
1160         LASSERT(dot_info != NULL); 
1161         LASSERT(data1 != NULL); 
1162         
1163         index = *(int *)data1; 
1164  
1165         if (smfs_primary_inode(inode) && 
1166             dentry->d_name.len == dot_info->dot_name_len &&
1167             memcmp(dentry->d_name.name, dot_info->dot_name, 
1168                    strlen(dot_info->dot_name)) == 0) {
1169                 struct inode *dot_inode = NULL; 
1170                 
1171                 dot_inode = smfs_get_inode(inode->i_sb, inode->i_ino, inode,
1172                                            DOT_SNAP_INDEX);
1173                 smfs_init_snap_inode_info(dot_inode, inode, DOT_SNAP_INDEX);
1174                 d_add(dentry, dot_inode);
1175                 rc = 1;
1176                 RETURN(rc);
1177         }
1178         if (smfs_dotsnap_inode(inode)) {
1179                 rc = smfs_dotsnap_lookup(inode, dentry, snap_info);
1180                 if (rc == 0)
1181                         rc = 1;
1182                 RETURN(rc);                
1183         } 
1184         if (index > 0) {
1185                 /*HERE: will replace ino in dentry->d_name according to index*/ 
1186                 struct fsfilt_operations *snapops = I2SNAPOPS(inode);
1187                 char *name = (char *)dentry->d_name.name;
1188                 unsigned long ino, hash, ind_ino; 
1189                 int len = sizeof(ind_ino);
1190                  
1191                 ino = simple_strtoul(name, 0, 0);         
1192
1193                 ind_ino = snapops->fs_get_indirect_ino(inode->i_sb, ino, index);
1194                 
1195                 snprintf(name, strlen(name), "0x%lx", ind_ino);                 
1196                 
1197                 hash = init_name_hash();
1198                 while (len--) {
1199                         unsigned char c; 
1200                         c = *(const unsigned char *)name++;
1201                         if (c == '\0') break;
1202                         hash = partial_name_hash(c, hash);
1203                 }
1204                 dentry->d_name.hash = end_name_hash(hash);
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 typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry, 
1247                          void *new_dir, void *new_dentry);
1248
1249 static cow_funcs smfs_cow_pre_funcs[HOOK_MAX + 1] = {
1250         [HOOK_CREATE]   smfs_cow_create,
1251         [HOOK_LOOKUP]   smfs_cow_lookup,
1252         [HOOK_LINK]     smfs_cow_link,
1253         [HOOK_UNLINK]   smfs_cow_unlink,
1254         [HOOK_SYMLINK]  smfs_cow_create,
1255         [HOOK_MKDIR]    smfs_cow_create,
1256         [HOOK_RMDIR]    smfs_cow_unlink, 
1257         [HOOK_MKNOD]    smfs_cow_create,
1258         [HOOK_RENAME]   smfs_cow_rename,
1259         [HOOK_SETATTR]  smfs_cow_setattr,
1260         [HOOK_WRITE]    smfs_cow_write,
1261 };
1262 int smfs_cow_lookup_post(struct inode *dir, struct dentry *dentry, void *data1,
1263                          void *data2)
1264 {
1265         struct inode *inode = dentry->d_inode; 
1266         struct fsfilt_operations *sops = I2SNAPCOPS(inode); 
1267         int index = I2SNAPI(dir)->sn_index;
1268         ENTRY;
1269
1270         LASSERT(inode);
1271       
1272         if (index > 0) {
1273                 struct inode *cache_ind = NULL;
1274
1275                 cache_ind = sops->fs_get_indirect(I2CI(inode), NULL, index);
1276                 if (cache_ind->i_ino != I2CI(inode)->i_ino) {
1277                         struct inode *ind_inode = NULL;
1278                         
1279                         ind_inode = smfs_get_inode(dir->i_sb, cache_ind->i_ino,
1280                                                    dir, index);
1281                         /*replace the ind_inode here*/ 
1282                         list_del_init(&dentry->d_alias);
1283                         iput(inode);
1284                         d_instantiate(dentry, ind_inode); 
1285                 }
1286         }
1287         inode = dentry->d_inode;
1288  
1289         smfs_init_snap_inode_info(inode, dir, index);
1290         
1291         RETURN(0);
1292 }
1293
1294 static cow_funcs smfs_cow_post_funcs[HOOK_MAX + 1] = {
1295         [HOOK_CREATE]   NULL,
1296         [HOOK_LOOKUP]   smfs_cow_lookup_post,
1297         [HOOK_LINK]     NULL,
1298         [HOOK_UNLINK]   NULL,
1299         [HOOK_SYMLINK]  NULL,
1300         [HOOK_MKDIR]    NULL,
1301         [HOOK_RMDIR]    NULL, 
1302         [HOOK_MKNOD]    NULL,
1303         [HOOK_RENAME]   NULL,
1304         [HOOK_SETATTR]  NULL,
1305         [HOOK_WRITE]    NULL,
1306 };
1307
1308 static int smfs_cow_pre(struct inode *dir, struct dentry *dentry, void *new_dir, 
1309                         void *new_dentry, int op)
1310 {
1311         if (smfs_cow_pre_funcs[op]) {
1312                 return smfs_cow_pre_funcs[op](dir, dentry, new_dir, new_dentry);
1313         }
1314         return 0;
1315 }
1316
1317 static int smfs_cow_post(struct inode *dir, struct dentry *dentry, void *new_dir, 
1318                          void *new_dentry, int op)
1319 {
1320         if (smfs_cow_post_funcs[op]) {
1321                 return smfs_cow_post_funcs[op](dir, dentry, new_dir, new_dentry);
1322         }
1323         return 0;
1324 }
1325