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