Whamcloud - gitweb
1)cleanup smfs for build in 2.6
[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 #define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) + size * sizeof(struct snap)) 
44 static int smfs_init_snaptabe(struct super_block *sb)
45 {
46         struct snap_info         *snap_info = S2SNAPI(sb);      
47         struct snap_table        *snap_table = NULL;       
48         struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
49         struct dentry            *d_root = snap_info->snap_root;
50         int                      rc = 0, size, table_size, vallen, i;
51  
52         ENTRY;
53
54         init_MUTEX(&snap_info->sntbl_sema);
55         /*Initialized table */
56         /*get the maxsize of snaptable*/
57         vallen = sizeof(int);
58         rc = snapops->fs_get_snap_info(d_root->d_inode, MAX_SNAPTABLE_COUNT,
59                                        strlen(MAX_SNAPTABLE_COUNT), &size, 
60                                        &vallen);
61         if (size == 0) {
62                 CERROR("the Max snaptable count should not be zero\n");
63                 RETURN(-EINVAL);
64         }
65         
66         table_size = SNAPTABLE_SIZE(size);
67
68         OBD_ALLOC(snap_info->sntbl, table_size);
69
70         if (!snap_info->sntbl) {
71                 CERROR("No MEM\n");
72                 RETURN(-ENOMEM);
73         }
74         snap_table = snap_info->sntbl;
75          
76         snap_table->sntbl_magic = cpu_to_le32((__u32)SNAPTABLE_MAGIC); 
77         snap_table->sntbl_max_count = size;
78         for (i = 0; i < snap_table->sntbl_max_count; i++) {
79                 /*init sn_index to -1*/ 
80                 snap_table->sntbl_items[i].sn_index = -1;
81         }
82         /*get snaptable info*/
83         rc = snapops->fs_get_snap_info(d_root->d_inode, SNAPTABLE_INFO, 
84                                        strlen(SNAPTABLE_INFO), 
85                                        snap_table, &table_size);       
86         if (rc < 0) {
87                 if (rc == -ENODATA) {
88                         snap_table->sntbl_count = 0;
89                         CDEBUG(D_INFO, "No snaptable here\n");
90                         RETURN(0);
91                 } else {
92                         CERROR("Can not retrive the snaptable from this filesystem\n");
93                         OBD_FREE(snap_table, table_size);
94                         RETURN(rc); 
95                 }
96         } 
97         if (le32_to_cpu(snap_table->sntbl_magic) != SNAPTABLE_MAGIC) {
98                 CERROR("On disk snaptable is not right \n");
99                 OBD_FREE(snap_table, table_size);
100                 RETURN(-EIO);
101         }
102         RETURN(rc);
103 }
104 #define COWED_NAME_LEN       (7 + 8 + 1) 
105 static int smfs_init_cowed_dir(struct super_block *sb, struct dentry* cowed_dir)  
106 {
107         struct snap_info *snap_info = S2SNAPI(sb);      
108         struct dentry    *dentry = NULL;
109         struct lvfs_run_ctxt saved;
110         char   name[COWED_NAME_LEN];
111         int    rc = 0;
112         ENTRY;
113          
114         sprintf(name, ".cowed_%08x", (__u32)cowed_dir->d_inode->i_ino);
115         push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
116         dentry = simple_mkdir(cowed_dir, name, 0777, 1);
117         pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
118         if (IS_ERR(dentry)) {
119                 rc = PTR_ERR(dentry);
120                 CERROR("create cowed directory: rc = %d\n", rc);
121                 RETURN(rc);
122         }
123         snap_info->sn_cowed_dentry = dentry;
124         RETURN(rc);
125 }
126 static int smfs_init_dotinfo(struct super_block *sb)
127 {
128         struct snap_info *snap_info = S2SNAPI(sb);
129         struct snap_dot_info *dot_info = NULL;
130         int rc = 0;
131         ENTRY;
132
133         if (snap_info->sn_dot_info)
134                 RETURN(-EEXIST);
135        
136         OBD_ALLOC(snap_info->sn_dot_info, sizeof(struct snap_dot_info));
137         
138         if (!snap_info->sn_dot_info)
139                 RETURN(-ENOMEM); 
140       
141         dot_info = snap_info->sn_dot_info;
142  
143         OBD_ALLOC(dot_info->dot_name,  strlen(DOT_SNAP_NAME) + 1);
144
145         if (!dot_info->dot_name) {
146                 OBD_FREE(snap_info->sn_dot_info, sizeof(struct snap_dot_info));
147                 RETURN(-ENOMEM); 
148         } 
149         memcpy(dot_info->dot_name, DOT_SNAP_NAME, strlen(DOT_SNAP_NAME));
150         
151         dot_info->dot_name_len = strlen(DOT_SNAP_NAME); 
152         dot_info->dot_snap_enable = 1;
153         
154         RETURN(rc);
155 }
156
157 static int smfs_cleanup_dotinfo(struct super_block *sb)
158 {       
159         struct snap_info *snap_info = S2SNAPI(sb);
160         struct snap_dot_info *dot_info = NULL;
161         int rc = 0;
162         ENTRY;
163
164         if (!snap_info->sn_dot_info)
165                 RETURN(rc);
166        
167         dot_info = snap_info->sn_dot_info;
168
169         if (dot_info->dot_name) { 
170                 OBD_FREE(dot_info->dot_name, dot_info->dot_name_len + 1);
171         }
172         
173         OBD_FREE(dot_info, sizeof(struct snap_dot_info));
174
175         RETURN(rc);
176 }
177
178 int smfs_start_cow(struct super_block *sb)
179 {
180         int rc = 0;
181
182         ENTRY;
183         
184         /*init snap fsfilt operations*/
185         if (!S2SNAPI(sb)->snap_cache_fsfilt) {
186                 char *snap_cache_ftype = NULL;
187                 int   tmp = strlen(S2SMI(sb)->smsi_cache_ftype) + strlen("_snap");
188                 
189                 OBD_ALLOC(snap_cache_ftype, tmp + 1);  
190                 sprintf(snap_cache_ftype, "%s_snap", S2SMI(sb)->smsi_cache_ftype);
191                 S2SNAPI(sb)->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype);
192                 OBD_FREE(snap_cache_ftype, tmp + 1);
193                 if (!S2SNAPI(sb)->snap_cache_fsfilt) {
194                         CERROR("Can not get %s fsfilt ops needed by snap\n",
195                                snap_cache_ftype);
196                         RETURN(-EINVAL);
197                 }
198         }
199         if (!S2SNAPI(sb)->snap_fsfilt) {
200                 char *snap_ftype = NULL;
201                 int   tmp = strlen(S2SMI(sb)->smsi_ftype) + strlen("_snap");
202                 
203                 OBD_ALLOC(snap_ftype, tmp + 1);  
204                 sprintf(snap_ftype, "%s_snap", S2SMI(sb)->smsi_ftype);
205                 S2SNAPI(sb)->snap_fsfilt = fsfilt_get_ops(snap_ftype);
206                 OBD_FREE(snap_ftype, tmp + 1);
207                 if (!S2SNAPI(sb)->snap_fsfilt) {
208                         CERROR("Can not get %s fsfilt ops needed by snap\n",
209                                snap_ftype);
210                         RETURN(-EINVAL);
211                 }
212         }
213         rc = smfs_init_snaptabe(sb); 
214         if (rc) {
215                 CERROR("can not init snaptable rc=%d\n", rc);
216                 RETURN(rc);
217         }
218         /*init dot snap info*/
219         rc = smfs_init_dotinfo(sb);
220         if (rc) {
221                 CERROR("can not init dot snap info rc=%d\n", rc);
222                 RETURN(rc);
223         }
224         /*init cowed dir to put the primary cowed inode
225          *FIXME-WANGDI, later the s_root may not be the 
226          *snap dir, we can indicate any dir to be cowed*/
227         rc = smfs_init_cowed_dir(sb, sb->s_root);
228         RETURN(rc);
229 }
230 EXPORT_SYMBOL(smfs_start_cow);
231 int smfs_stop_cow(struct super_block *sb)
232 {
233         struct snap_info       *snap_info = S2SNAPI(sb);        
234         struct snap_table      *snap_table = snap_info->sntbl;  
235         int rc = 0, table_size;
236         ENTRY;
237
238         l_dput(snap_info->sn_cowed_dentry);
239          
240         if (snap_info->snap_fsfilt) 
241                 fsfilt_put_ops(snap_info->snap_fsfilt);
242         if (snap_info->snap_cache_fsfilt)
243                 fsfilt_put_ops(snap_info->snap_cache_fsfilt);
244
245         if (snap_table) {
246                 table_size =  SNAPTABLE_SIZE(snap_table->sntbl_max_count);
247                 OBD_FREE(snap_info->sntbl, table_size);
248         }
249         smfs_cleanup_dotinfo(sb);
250          
251         RETURN(rc);
252 }
253 EXPORT_SYMBOL(smfs_stop_cow);
254
255 #define COW_HOOK "cow_hook"
256 static int smfs_cow_pre_hook(struct inode *inode, struct dentry *dentry, 
257                              void *data1, void *data2, int op, void *handle)
258 {
259         int rc = 0;
260         ENTRY;
261  
262         if (smfs_do_cow(inode)) {                                              
263                 rc = smfs_cow(inode, dentry, data1, data2, op);           
264         }
265         RETURN(rc);                                                                     
266 }
267 int smfs_cow_init(struct super_block *sb)
268 {
269         struct smfs_super_info *smfs_info = S2SMI(sb);
270         struct smfs_hook_ops *cow_hops = NULL;
271         int rc = 0;
272
273         ENTRY;
274
275         SMFS_SET_COW(smfs_info);
276       
277         cow_hops = smfs_alloc_hook_ops(COW_HOOK, smfs_cow_pre_hook, NULL);
278         if (!cow_hops) {
279                 RETURN(-ENOMEM);
280         }
281  
282         rc = smfs_register_hook_ops(sb, cow_hops);      
283
284         if (rc) {
285                 smfs_free_hook_ops(cow_hops);
286                 RETURN(rc);
287         }
288  
289         OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info));
290         
291         if (!smfs_info->smsi_snap_info) 
292                 GOTO(exit, rc = -ENOMEM);
293 exit:
294         if (rc && cow_hops) {
295                 smfs_unregister_hook_ops(sb, cow_hops->smh_name);
296                 smfs_free_hook_ops(cow_hops);
297         } 
298         RETURN(rc);
299 }
300
301 int smfs_cow_cleanup(struct super_block *sb)
302 {
303         
304         struct snap_info   *snap_info = S2SNAPI(sb);    
305         struct smfs_hook_ops *cow_hops; 
306         ENTRY;
307
308         cow_hops = smfs_unregister_hook_ops(sb, COW_HOOK);
309         smfs_free_hook_ops(cow_hops);
310
311         SMFS_CLEAN_COW(S2SMI(sb));
312         if (snap_info) 
313                OBD_FREE(snap_info, sizeof(*snap_info)); 
314         RETURN(0);
315 }
316
317 static int smfs_dotsnap_dir_size(struct inode *inode)
318 {
319         struct snap_info *snap_info = S2SNAPI(inode->i_sb);
320         struct fsfilt_operations *snapops = snap_info->snap_cache_fsfilt; 
321         struct snap_table *stbl = snap_info->sntbl;
322         int size = 0, dir_size = 0, blocks;
323         int i = 0;
324         ENTRY;
325
326         for (i = 0; i < stbl->sntbl_count; i++) {
327                 size += snapops->fs_dir_ent_size(stbl->sntbl_items[i].sn_name);
328         }
329         /*FIXME this is only for ext3 dir format, may need fix for other FS*/ 
330         blocks = (size + inode->i_sb->s_blocksize - 1) >> 
331                                 inode->i_sb->s_blocksize_bits; 
332         
333         dir_size = blocks * inode->i_sb->s_blocksize; 
334         RETURN(dir_size); 
335
336
337 /*FIXME Note indirect and primary inode 
338 * should be recorgnized here*/
339 int smfs_init_snap_inode_info(struct inode *inode, 
340                               struct snap_inode_info *sn_info) 
341 {
342         struct smfs_inode_info *smi = I2SMI(inode);
343         int vallen, rc = 0;
344         ENTRY;
345
346         LASSERT(sn_info && smi);
347         smi->sm_sninfo.sn_flags = sn_info->sn_flags;
348         smi->sm_sninfo.sn_gen = sn_info->sn_gen;
349         smi->sm_sninfo.sn_index = sn_info->sn_index; 
350
351         if (smfs_dotsnap_inode(inode)) {
352                 struct snap_table *stbl= S2SNAPI(inode->i_sb)->sntbl;
353                 int size = 0;
354                 /*init dot_snap inode info*/
355                 size = smfs_dotsnap_dir_size(inode); 
356                 inode->i_size = (loff_t)size;                   
357                 inode->i_nlink = stbl->sntbl_count + 2;
358                 inode->i_uid = 0;
359                 inode->i_gid = 0;
360         } else if (SMFS_DO_COW(S2SMI(inode->i_sb)) && 
361                    (smi->smi_flags & SM_DO_COW) &&
362                    smfs_primary_inode(inode)) {
363                 struct snap_inode_info *sni_info = I2SNAPI(inode);
364                 struct fsfilt_operations *snapops = I2SNAPOPS(inode);
365                 
366                 vallen = sizeof(sni_info->sn_gen);
367                 
368                 rc = snapops->fs_get_snap_info(inode, SNAP_GENERATION,
369                                                strlen(SNAP_GENERATION),
370                                                &sni_info->sn_gen, &vallen);               
371         } 
372         RETURN(rc);                                              
373 }
374 /* latest snap: returns 
375    -  the index of the latest snapshot before NOW
376    -  hence it returns 0 in case all the volume snapshots lie in the future
377    -  this is the index where a COW will land (will be created) 
378 */
379 void snap_last(struct super_block *sb, struct snap *snap)
380 {
381         struct snap_info *snap_info = S2SNAPI(sb);
382         struct snap_table *table = snap_info->sntbl;
383         time_t now = LTIME_S(CURRENT_TIME);
384         int i ;
385
386         ENTRY;
387         /* start at the highest index in the superblock snaptime array */ 
388         if (table->sntbl_count == 0) {
389                memset(snap, 0, sizeof(struct snap)); 
390         } else {
391                 i = table->sntbl_count - 1;
392                 snap->sn_index = table->sntbl_items[i].sn_index;
393                 snap->sn_time = table->sntbl_items[i].sn_time;
394                 snap->sn_gen = table->sntbl_items[i].sn_gen;
395         }
396         CDEBUG(D_INFO, "index: %d, time[i]: %ld, now: %ld\n",
397                snap->sn_index, snap->sn_time, now);
398         EXIT;
399         return;
400 }
401
402 static int inline get_index_of_item(struct snap_table *table, char *name)
403 {
404         int count = table->sntbl_count;
405         int i, j;
406         ENTRY;
407         
408         for (i = 0; i < table->sntbl_max_count; i++) { 
409                 if (!strcmp(name, table->sntbl_items[i].sn_name)) {
410                         CERROR("Duplicate name %s in snaptable\n", name); 
411                         RETURN(-EINVAL);
412                 }       
413         }
414
415         for (i = 0; i < table->sntbl_max_count; i++) {
416                 int found = 0;
417                 for (j = 0; j < (count + 1); j++) {
418                         if (table->sntbl_items[j].sn_index == i) {
419                                 found = 1;
420                                 break;  
421                         }
422                 }
423                 if (!found)
424                         RETURN(i);
425         }
426         CERROR("snaptable Full\n");
427         RETURN(-ENOSPC);
428 }
429
430 int smfs_add_snap_item(struct super_block *sb, char *name)
431 {
432         struct snap_info *snap_info = S2SNAPI(sb);
433         struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
434         struct snap_table *snap_table = snap_info->sntbl;
435         struct dentry            *d_root = snap_info->snap_root;
436         struct snap      *snap_item;
437         int    table_size, count = 0, index = 0, rc = 0;
438
439         count = snap_table->sntbl_count; 
440         /* XXX Is down this sema necessary*/
441         down_interruptible(&snap_info->sntbl_sema);
442         snap_item = &snap_table->sntbl_items[count];
443
444         /*add item in snap_table set generation*/
445         snap_item->sn_time = LTIME_S(CURRENT_TIME);
446         /* find table index */
447         index = get_index_of_item(snap_table, name);
448         if (index < 0) 
449                 GOTO(exit, rc = index);
450         
451         snap_item->sn_index = index;
452         snap_item->sn_flags = 0;
453         snap_item->sn_gen = snap_table->sntbl_generation + 1; 
454         memcpy(snap_item->sn_name, name, SNAP_MAX_NAMELEN);
455         /* Wrote the whole snap_table to disk */
456         table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count); 
457         
458         rc = snapops->fs_set_snap_info(d_root->d_inode, SNAPTABLE_INFO, 
459                                        strlen(SNAPTABLE_INFO),
460                                        snap_table, &table_size);
461         if (rc) {
462                 CERROR("Set snaptable error rc=%d\n", rc);
463                 GOTO(exit, rc);
464         }
465         snap_table->sntbl_count++;
466         snap_table->sntbl_generation++;
467 exit:
468         up(&snap_info->sntbl_sema);
469         RETURN(rc);
470 }
471 EXPORT_SYMBOL(smfs_add_snap_item);
472 /*
473  * Note: this function should be differnet with snap_do_cow.
474  * In smfs_do_cow, we check the EA for whether do cow for that inode.
475  * In smfs_needs_cow, we check whether we do need to do cow. 
476  */
477 int smfs_needs_cow(struct inode *inode)
478 {
479         struct smfs_inode_info  *smi_info = I2SMI(inode); 
480         struct snap_inode_info *snap_info = NULL;
481         struct snap snap;
482         int index = -1;
483         ENTRY;
484
485         snap_info = &(smi_info->sm_sninfo);
486         
487         snap_last(inode->i_sb, &snap);
488         /* decision .... if the snapshot is more recent than the object,
489          * then any change to the object should cause a COW.
490          */
491         if (snap_info->sn_gen < snap.sn_gen ) 
492                 index = snap.sn_index;
493
494         CDEBUG(D_INFO, "snap_needs_cow, ino %lu , get index %d\n",
495                inode->i_ino, index);
496
497         RETURN(index);
498 } /* snap_needs_cow */
499
500 static int link_cowed_inode(struct inode *inode)
501 {
502         struct snap_info *snap_info = S2SNAPI(inode->i_sb);     
503         struct dentry *cowed_dir = NULL;
504         char fidname[LL_FID_NAMELEN];
505         int fidlen = 0, rc = 0;
506         struct dentry *dchild = NULL;
507         struct dentry *tmp = NULL;
508         unsigned mode;
509
510         cowed_dir = snap_info->sn_cowed_dentry;
511         
512         fidlen = ll_fid2str(fidname, inode->i_ino, inode->i_generation);
513
514         down(&cowed_dir->d_inode->i_sem);
515         dchild = ll_lookup_one_len(fidname, cowed_dir, fidlen);
516         if (IS_ERR(dchild)) {
517                 rc = PTR_ERR(dchild);
518                 if (rc != -EPERM && rc != -EACCES)
519                         CERROR("child lookup error %d\n", rc);
520                 GOTO(out_lock, rc);
521         }
522         if (dchild->d_inode != NULL) {
523                 CERROR("re-cowed file %s?\n", dchild->d_name.name);
524                 LASSERT(dchild->d_inode == inode);
525                 GOTO(out_dput, rc = 0);
526         }
527         tmp = pre_smfs_dentry(NULL, inode, cowed_dir, NULL);
528         /* link() is semanticaly-wrong for S_IFDIR, so we set S_IFREG
529          * for linking and return real mode back then -bzzz */
530         mode = inode->i_mode;
531         inode->i_mode = S_IFREG;
532         rc = vfs_link(tmp, cowed_dir->d_inode, dchild);
533         post_smfs_dentry(tmp);
534         if (rc) {
535                 CERROR("error linking cowed inode %s to COWED: rc = %d\n",
536                         fidname, rc);
537         } 
538         inode->i_mode = mode;
539         if ((mode & S_IFMT) == S_IFDIR) {
540                 dchild->d_inode->i_nlink++;
541                 cowed_dir->d_inode->i_nlink++;
542         }
543         mark_inode_dirty(dchild->d_inode);
544 out_dput:
545         dput(dchild);
546 out_lock:       
547         up(&cowed_dir->d_inode->i_sem);
548         RETURN(rc);
549 }
550 /*
551  * Make a copy of the data and plug a redirector in between if there
552  * is no redirector yet.
553  */
554 int snap_do_cow(struct inode *inode, struct dentry *dparent, int del)
555 {
556         struct snap_info *snap_info = S2SNAPI(inode->i_sb);     
557         struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
558         struct snap snap;
559         struct inode *ind = NULL;
560
561         ENTRY;
562
563         if (!snapops || !snapops->fs_create_indirect) 
564                 RETURN(-EINVAL);
565
566         snap_last(inode->i_sb, &snap);
567         ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen, 
568                                           dparent->d_inode, del);
569         if(ind && IS_ERR(ind)) {
570                 CERROR("Create ind inode %lu index %d gen %d del %d rc%lu\n",
571                         inode->i_ino, snap.sn_index, snap.sn_gen, del,
572                         PTR_ERR(ind));
573                 RETURN(PTR_ERR(ind));
574         }
575         if (ind) { 
576                 if (!SMFS_DO_INODE_COWED(inode)) {
577                         /*insert the inode to cowed inode*/
578                         SMFS_SET_INODE_COWED(inode); 
579                         link_cowed_inode(inode); 
580                 }
581                 
582                 I2SMI(ind)->sm_sninfo.sn_flags = 0;
583                 I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen;
584                 I2SMI(ind)->sm_sninfo.sn_index = snap.sn_index;
585                 
586                 iput(ind);
587         }
588         RETURN(0);
589 }
590 /*Dir inode will do cow*/
591 int smfs_cow_create(struct inode *dir, struct dentry *dentry,
592                     void *data1, void *data2)
593 {
594         int rc = 0;
595         struct dentry *dparent;
596         ENTRY;
597
598         if (smfs_needs_cow(dir) != -1) {
599                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
600                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
601                 dparent = dentry->d_parent->d_parent;
602                 if ((rc = snap_do_cow(dir, dparent, 0))) {
603                         CERROR("Do cow error %d\n", rc);
604                         RETURN(-EINVAL);
605                 }
606         }
607         RETURN(rc);
608 }
609
610 int smfs_cow_setattr(struct inode *dir, struct dentry *dentry,
611                      void *data1, void *data2)
612 {
613         int rc = 0;
614         ENTRY;
615         if (smfs_needs_cow(dir) != -1) {
616                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
617                 if ((snap_do_cow(dir, dentry->d_parent, 0))) {
618                         CERROR("Do cow error\n");
619                         RETURN(-EINVAL);
620                 }
621         }
622         RETURN(rc);
623 }
624
625 int smfs_cow_link(struct inode *dir, struct dentry *dentry,
626                   void *data1, void *data2)
627 {
628         int rc = 0;
629         struct dentry *dparent;
630         ENTRY;
631  
632         if (smfs_needs_cow(dir) != -1) {
633                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
634                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
635                 dparent = dentry->d_parent->d_parent;
636                 if ((snap_do_cow(dir, dparent, 0))) {
637                         CERROR("Do cow error\n");
638                         RETURN(-EINVAL);
639                 }
640                 if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 0))) {
641                         CERROR("Do cow error\n");
642                         RETURN(-EINVAL);
643                 }
644         }
645         RETURN(rc);
646 }
647
648 int smfs_cow_unlink(struct inode *dir, struct dentry *dentry,
649                     void *data1, void *data2)
650 {
651         struct dentry *dparent;
652         int rc = 0;
653         ENTRY;
654
655         if (smfs_needs_cow(dir) != -1) {
656                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
657                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
658                 dparent = dentry->d_parent->d_parent;
659                 if ((snap_do_cow(dir, dparent, 0))) {
660                         CERROR("Do cow error\n");
661                         RETURN(-EINVAL);
662                 }
663                 if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 1))) {
664                         CERROR("Do cow error\n");
665                         RETURN(-EINVAL);
666                 }
667         
668         }
669         RETURN(rc);
670 }
671
672 int smfs_cow_rename(struct inode *dir, struct dentry *dentry, 
673                     void *data1, void *data2)
674 {
675         struct inode *new_dir = (struct inode *)data1;
676         struct dentry *new_dentry = (struct dentry *)data2;
677         struct dentry *dparent;
678         int rc = 0;
679         ENTRY;
680        
681         LASSERT(new_dir);
682         LASSERT(new_dentry); 
683         if (smfs_needs_cow(dir) != -1) {
684                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n", dir->i_ino);
685                 LASSERT(dentry->d_parent && dentry->d_parent->d_parent);
686                 dparent = dentry->d_parent->d_parent;
687                 if ((snap_do_cow(dir, dparent, 0))) {
688                         CERROR("Do cow error\n");
689                         RETURN(-EINVAL);
690                 }
691                 if ((snap_do_cow(dentry->d_inode, dentry->d_parent, 0))) {
692                         CERROR("Do cow error\n");
693                         RETURN(-EINVAL);
694                 }
695         }
696         if (smfs_needs_cow(new_dir) != -1) {
697                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n", new_dir->i_ino);
698                 LASSERT(new_dentry->d_parent && new_dentry->d_parent->d_parent);
699                 dparent = new_dentry->d_parent->d_parent;
700                 if ((new_dir != dir) && (snap_do_cow(new_dir, dparent, 0))){
701                         CERROR("Do cow error\n");
702                         RETURN(-EINVAL);
703                 }
704                 if (new_dentry->d_inode && new_dentry->d_inode->i_nlink == 1) {
705                         if ((snap_do_cow(new_dentry->d_inode, 
706                                          new_dentry->d_parent, 0))) {
707                                 CERROR("Do cow error\n");
708                                 RETURN(-EINVAL);
709                         }
710                 }
711         } 
712         RETURN(rc);
713 }
714
715 int smfs_cow_write(struct inode *inode, struct dentry *dentry, void *data1,
716                    void *data2)
717 {
718         struct snap_info *snap_info = S2SNAPI(inode->i_sb); 
719         struct snap_table *table = snap_info->sntbl; 
720         long   blocks[2]={-1,-1};
721         int  index = 0, i, rc = 0;
722         size_t count;
723         loff_t pos;
724
725         ENTRY;
726
727         LASSERT(data1);
728         LASSERT(data2);
729         
730         count = *(size_t *)data1;
731         pos = *(loff_t*)data2;
732  
733         down(&inode->i_sem);
734         
735         if (smfs_needs_cow(inode) != -1 ) {
736                 CDEBUG(D_INFO, "snap_needs_cow for ino %lu \n",inode->i_ino);
737                 snap_do_cow(inode, dentry->d_parent, 0);
738         }
739         
740         CDEBUG(D_INFO, "write offset %lld count %u \n", pos, count);
741         
742         if(pos & (PAGE_CACHE_SIZE - 1)){
743                 blocks[0] = pos >> inode->i_sb->s_blocksize_bits;
744         }
745         pos += count - 1;
746         if((pos + 1) & (PAGE_CACHE_SIZE - 1)){
747                 blocks[1] = pos >> inode->i_sb->s_blocksize_bits;
748         }
749
750         if (blocks[0] == blocks[1]) 
751                 blocks[1] = -1;
752         
753         for (i = 0; i < 2; i++) {
754                 int slot = 0;
755                 if (blocks[i] == -1) 
756                         continue;
757                 /*Find the nearest page in snaptable and copy back it*/
758                 for (slot = table->sntbl_count - 1; slot >= 0; slot--) {
759                         struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
760                         struct inode *cache_inode = NULL;
761                         int result = 0;
762
763                         index = table->sntbl_items[slot].sn_index;
764                         cache_inode = snapops->fs_get_indirect(inode, NULL, index);
765
766                         if (!cache_inode)  continue;
767
768                         CDEBUG(D_INFO, "find cache_ino %lu\n", cache_inode->i_ino);
769                 
770                         result = snapops->fs_copy_block(inode, cache_inode, blocks[i]);
771                         if (result == 1) {
772                                 iput(cache_inode);
773                                 result = 0;
774                                 break;
775                         }
776                         if (result < 0) {
777                                 iput(cache_inode);
778                                 up(&inode->i_sem);
779                                 GOTO(exit, rc = result);
780                         }
781                         iput(cache_inode);
782                 }
783         }
784 exit:
785         up(&inode->i_sem); 
786         RETURN(rc);
787 }
788 EXPORT_SYMBOL(smfs_cow_write);
789 /*lookup inode in dotsnap inode */
790 static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry)
791
792         if (dentry->d_name.len == 1 && 
793             !strcmp(dentry->d_name.name, ".")) {
794                 d_add(dentry, iget(dir->i_sb, dir->i_ino));
795         } else if (dentry->d_name.len == 2 && 
796                    !strcmp(dentry->d_name.name, "..")) {
797                 struct inode *inode;
798                 struct dentry *dparent = dentry->d_parent;                                                                                                                                                                                       
799                 if (dparent->d_inode) {
800                         inode = iget(dir->i_sb, dparent->d_inode->i_ino);
801                         if (inode) {
802                                 if (!is_bad_inode(inode))
803                                         d_add(dentry, inode);
804                                 else
805                                         iput(inode);
806                         }
807                 }
808         } else {
809                 /*find the name from the snaptable*/
810                 struct fsfilt_operations *snapops = I2SNAPOPS(dir);
811                 struct snap_table *table = S2SNAPI(dir->i_sb)->sntbl; 
812                 struct inode *inode;
813                 int i = 0, index = -1;
814                 for (i = 0; i < table->sntbl_count; i++) {
815                         char *name = table->sntbl_items[i].sn_name;
816                         if ((dentry->d_name.len == strlen(name)) &&
817                             (memcmp(dentry->d_name.name, name,
818                                     dentry->d_name.len) == 0)) {
819                                 index = table->sntbl_items[i].sn_index;
820                                 break;
821                         }
822                 }
823                 if (index != -1) {
824                        CERROR("No such %s in this .snap dir \n", 
825                                dentry->d_name.name);
826                        RETURN(-ENOENT);
827                 }
828                 inode = snapops->fs_get_indirect(dir, NULL, index);
829                 d_add(dentry, inode);
830         } 
831         RETURN(0);
832 }
833 int smfs_cow_lookup(struct inode *inode, struct dentry *dentry, void *data1,
834                     void *data2)
835 {
836         struct snap_info *snap_info = S2SNAPI(inode->i_sb);
837         struct snap_dot_info *dot_info = snap_info->sn_dot_info;
838         int rc = 0, index = 0;
839         ENTRY;
840
841         LASSERT(dot_info != NULL); 
842         LASSERT(data1 != NULL); 
843         
844         index = *(int *)data1; 
845  
846         if (smfs_primary_inode(inode) && 
847             dentry->d_name.len == dot_info->dot_name_len &&
848             memcmp(dentry->d_name.name, dot_info->dot_name, 
849                    strlen(dot_info->dot_name)) == 0) {
850                 struct inode *dot_inode = NULL; 
851                 
852                 dot_inode = smfs_get_inode(inode->i_sb, inode->i_ino, inode,
853                                            DOT_SNAP_INDEX);
854                 d_add(dentry, dot_inode);
855                 rc = 1;
856                 RETURN(rc);
857         }
858         if (smfs_dotsnap_inode(inode)) {
859                 rc = smfs_dotsnap_lookup(inode, dentry);
860                 if (rc == 0)
861                         rc = 1;
862                 RETURN(rc);                
863         } 
864         if (index > 0) {
865                 /*HERE: will replace ino in dentry->d_name according to index*/ 
866                 struct fsfilt_operations *snapops = I2SNAPOPS(inode);
867                 char *name = (char *)dentry->d_name.name;
868                 unsigned long ino, hash, ind_ino; 
869                 int len = sizeof(ind_ino);
870                  
871                 ino = simple_strtoul(name, 0, 0);         
872
873                 ind_ino = snapops->fs_get_indirect_ino(inode->i_sb, ino, index);
874                 
875                 snprintf(name, strlen(name), "0x%lx", ind_ino);                 
876                 
877                 hash = init_name_hash();
878                 while (len--) {
879                         unsigned char c; 
880                         c = *(const unsigned char *)name++;
881                         if (c == '\0') break;
882                         hash = partial_name_hash(c, hash);
883                 }
884                 dentry->d_name.hash = end_name_hash(hash);
885         }        
886         RETURN(rc);         
887 }
888
889 struct inode *smfs_cow_get_ind(struct inode *inode, int index)
890 {
891         struct snap_info *snap_info = S2SNAPI(inode->i_sb);
892         struct fsfilt_operations *snapops = snap_info->snap_fsfilt; 
893         struct snap_table *table = snap_info->sntbl;
894         long block=(index << PAGE_CACHE_SHIFT) >> inode->i_sb->s_blocksize_bits;
895         int slot;
896
897         ENTRY; 
898         for (slot = table->sntbl_count - 1; slot >= 0; slot--) {
899                 struct address_space_operations *aops = inode->i_mapping->a_ops;
900                 struct inode *cache_inode = NULL;
901                 int index = 0;
902
903                 index = table->sntbl_items[slot].sn_index;
904                 cache_inode = snapops->fs_get_indirect(inode, NULL, index);
905                                                                                                                                                                                                      
906                 if (!cache_inode )  continue;
907                                                                                                                                                                                                      
908                 if (aops->bmap(cache_inode->i_mapping, block))
909                        RETURN(cache_inode); 
910                 iput(cache_inode);
911         }
912
913         RETURN(NULL);
914 }
915 EXPORT_SYMBOL(smfs_cow_get_ind);
916
917 typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry, 
918                          void *new_dir, void *new_dentry);
919
920 static cow_funcs smfs_cow_funcs[HOOK_MAX + 1] = {
921         [HOOK_CREATE]   smfs_cow_create,
922         [HOOK_LOOKUP]   smfs_cow_lookup,
923         [HOOK_LINK]     smfs_cow_link,
924         [HOOK_UNLINK]   smfs_cow_unlink,
925         [HOOK_SYMLINK]  smfs_cow_create,
926         [HOOK_MKDIR]    smfs_cow_create,
927         [HOOK_RMDIR]    smfs_cow_unlink, 
928         [HOOK_MKNOD]    smfs_cow_create,
929         [HOOK_RENAME]   smfs_cow_rename,
930         [HOOK_SETATTR]  smfs_cow_setattr,
931         [HOOK_WRITE]    smfs_cow_write,
932 };
933
934 int smfs_cow(struct inode *dir, struct dentry *dentry, void *new_dir, 
935              void *new_dentry, int op)
936 {
937         if (smfs_cow_funcs[op]) {
938                 return smfs_cow_funcs[op](dir, dentry, new_dir, new_dentry);
939         }
940         return 0;
941 }
942