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