Whamcloud - gitweb
update snapfs 1. fix bug in write table_count in write snap_table 2. fixbug in repla...
[fs/lustre-release.git] / lustre / snapfs / dir.c
1 /*
2  * dir.c
3  */
4 #define DEBUG_SUBSYSTEM S_SNAP
5
6 #include <linux/module.h>
7 #include <linux/kernel.h>
8 #include <linux/string.h>
9 #include <linux/slab.h>
10 #include <linux/stat.h>
11 #include <linux/unistd.h>
12 #include <linux/jbd.h>
13 #include <linux/ext3_fs.h>
14 #include <linux/snap.h>
15
16 #include "snapfs_internal.h" 
17
18 static ino_t get_parent_ino(struct inode * inode)
19 {
20         ino_t ino = 0;
21         struct dentry * dentry;
22
23         if (list_empty(&inode->i_dentry)) {
24                 CERROR("No dentry for ino %lu\n", inode->i_ino);
25                 return 0;
26         }
27
28         dentry = dget(list_entry(inode->i_dentry.next, struct dentry, d_alias));
29
30         if(dentry->d_parent->d_inode)
31                 ino = dentry->d_parent->d_inode->i_ino;
32
33         dput(dentry);
34         return ino;
35
36 }
37
38 static void d_unadd_iput(struct dentry *dentry)
39 {
40         list_del(&dentry->d_alias);
41         INIT_LIST_HEAD(&dentry->d_alias);
42         list_del(&dentry->d_hash);
43         INIT_LIST_HEAD(&dentry->d_hash);
44         iput(dentry->d_inode);
45         dentry->d_inode = NULL;
46 }
47
48 /* XXX check the return values */
49 static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
50 {
51         struct snap_cache *cache;
52         struct dentry *rc;
53         struct inode_operations *iops;
54         struct inode *cache_inode;
55         int index;
56
57         ENTRY;
58
59         cache = snap_find_cache(dir->i_dev);
60         if ( !cache ) { 
61                 RETURN(ERR_PTR(-EINVAL));
62         }
63
64         if ( dentry->d_name.len == strlen(".snap") &&
65              (memcmp(dentry->d_name.name, ".snap", strlen(".snap")) == 0) ) {
66                 struct inode *snap;
67                 ino_t ino;
68
69                 /* Don't permit .snap in clonefs */
70                 if( dentry->d_sb != cache->cache_sb )
71                         RETURN(ERR_PTR(-ENOENT));
72
73                 /* Don't permit .snap under .snap */
74                 if( currentfs_is_under_dotsnap(dentry) )
75                         RETURN(ERR_PTR(-ENOENT));
76
77                 ino = 0xF0000000 | dir->i_ino;
78                 snap = iget(dir->i_sb, ino);
79                 CDEBUG(D_INODE, ".snap inode ino %ld, mode %o\n", snap->i_ino, snap->i_mode);
80                 d_add(dentry, snap);
81                 RETURN(NULL);
82         }
83
84         iops = filter_c2cdiops(cache->cache_filter); 
85         if (!iops || !iops->lookup) {
86                 RETURN(ERR_PTR(-EINVAL));
87         }
88
89         rc = iops->lookup(dir, dentry);
90         if ( rc || !dentry->d_inode) {
91                 RETURN(NULL);
92         }
93         
94         /*
95          * If we are under dotsnap, we need save extra data into
96          * dentry->d_fsdata:  For dir, we only need _this_ snapshot's index; 
97          * For others, save primary ino, with it we could found index later
98          * anyway
99          */
100         cache_inode = dentry->d_inode;
101         if ( (index = currentfs_is_under_dotsnap(dentry)) ) {
102                 struct snapshot_operations *snapops;
103                 struct inode *ind_inode;
104                 ino_t pri_ino, ind_ino;
105                
106                 pri_ino = cache_inode->i_ino;
107                 snapops = filter_c2csnapops(cache->cache_filter);
108                 if( !snapops )
109                         goto err_out;
110
111                 ind_ino = snapops->get_indirect_ino(cache_inode, index);
112                 if( ind_ino <=0 && ind_ino != -ENOATTR )
113                         goto err_out;
114                 else if( ind_ino != -ENOATTR ){
115                         ind_inode = iget(cache_inode->i_sb, ind_ino);
116                         if( !ind_inode ){
117                                 goto err_out;
118                         }
119                         list_del(&dentry->d_alias);
120                         INIT_LIST_HEAD(&dentry->d_alias);
121                         list_add(&dentry->d_alias, &ind_inode->i_dentry);
122                         dentry->d_inode = ind_inode;
123                         iput(cache_inode);
124                 }
125
126                 if( S_ISDIR(dentry->d_inode->i_mode) )
127                         dentry->d_fsdata = (void*)index;
128                 else
129                         dentry->d_fsdata = (void*)pri_ino;
130         }
131
132         RETURN(NULL);
133
134 #if 0
135         /* XXX: PJB these need to be set up again. See dcache.c */
136         printk("set up dentry ops\n");
137         CDEBUG(D_CACHE, "\n");
138         filter_setup_dentry_ops(cache->cache_filter,
139                                 dentry->d_op, &currentfs_dentry_ops);
140         dentry->d_op = filter_c2udops(cache->cache_filter);
141         CDEBUG(D_CACHE, "\n");
142 #endif
143
144 err_out:
145         d_unadd_iput(dentry);
146         RETURN(ERR_PTR(-EINVAL));
147 }
148
149 static int currentfs_create(struct inode *dir, struct dentry *dentry, int mode)
150 {
151         struct snap_cache       *cache;
152         struct inode_operations *iops;
153         void                    *handle = NULL;
154         int                     rc;
155
156         ENTRY;
157
158         if (currentfs_is_under_dotsnap(dentry)) {
159                 RETURN(-EPERM);
160         }
161
162         cache = snap_find_cache(dir->i_dev);
163         if ( !cache ) { 
164                 RETURN(-EINVAL);
165         }
166
167         handle = snap_trans_start(cache, dir, SNAP_OP_CREATE);
168
169         if ( snap_needs_cow(dir) != -1 ) {
170                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
171                 snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 1);
172                 if ((snap_do_cow(dir, get_parent_ino(dir), 0))) {
173                         CERROR("Do cow error\n");
174                         RETURN(-EINVAL);
175                 }
176         }
177
178         iops = filter_c2cdiops(cache->cache_filter); 
179         if (!iops || !iops->create) {
180                 RETURN(-EINVAL);
181         }
182         snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 2);
183         rc = iops->create(dir, dentry, mode);
184
185         /* XXX now set the correct snap_{file,dir,sym}_iops */
186         if (!dentry->d_inode) {
187                 CERROR("Error in currentfs_create, dentry->d_inode is NULL\n");
188                 GOTO(exit, 0);
189         }
190         set_filter_ops(cache, dentry->d_inode);
191         CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
192         snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 3);
193         init_filter_data(dentry->d_inode, 0); 
194 exit:
195         snap_trans_commit(cache, handle);
196         RETURN(rc);
197 }
198
199 static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
200 {
201         struct snap_cache *cache;
202         int rc;
203         struct inode_operations *iops;
204         void *handle = NULL;
205
206         ENTRY;
207
208         if (currentfs_is_under_dotsnap(dentry)) {
209                 RETURN(-EPERM);
210         }
211
212         cache = snap_find_cache(dir->i_dev);
213         if ( !cache ) { 
214                 RETURN(-EINVAL);
215         }
216
217         handle = snap_trans_start(cache, dir, SNAP_OP_MKDIR);
218
219         if ( snap_needs_cow(dir) != -1 ) {
220                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
221                 snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 1);
222                 snap_do_cow(dir, get_parent_ino(dir), 0);
223         }
224
225         iops = filter_c2cdiops(cache->cache_filter); 
226         if (!iops || !iops->mkdir) {
227                 rc = -EINVAL;
228                 goto exit;
229         }
230
231         snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 2);
232         rc = iops->mkdir(dir, dentry, mode);
233
234         if ( rc ) 
235                 goto exit;
236                      
237         /* XXX now set the correct snap_{file,dir,sym}_iops */
238         if ( dentry->d_inode) {
239                 dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter);
240                 CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
241         } else {
242                 CERROR("Error in currentfs_mkdir, dentry->d_inode is NULL\n");
243         }
244
245         snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 3);
246         
247 exit:
248         snap_trans_commit(cache, handle);
249         RETURN(rc);
250 }
251
252 static int currentfs_link (struct dentry * old_dentry, struct inode * dir, 
253                         struct dentry *dentry)
254 {
255         struct snap_cache *cache;
256         int rc;
257         struct inode_operations *iops;
258         void *handle = NULL;
259
260         ENTRY;
261
262         if (currentfs_is_under_dotsnap(dentry)) 
263                 RETURN(-EPERM);
264
265         cache = snap_find_cache(dir->i_dev);
266         if ( !cache )  
267                 RETURN(-EINVAL);
268
269         handle = snap_trans_start(cache, dir, SNAP_OP_LINK);
270
271         if ( snap_needs_cow(dir) != -1 ) {
272                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
273                 snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 1);
274                 snap_do_cow(dir, get_parent_ino(dir), 0);
275         }
276         if ( snap_needs_cow(old_dentry->d_inode) != -1 ) {
277                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",old_dentry->d_inode->i_ino);
278                 snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 2);
279                 snap_do_cow(old_dentry->d_inode, dir->i_ino, 0);
280         }
281
282         iops = filter_c2cdiops(cache->cache_filter); 
283
284         if (!iops || !iops->link) 
285                 GOTO(exit, rc = -EINVAL);
286         
287         snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 2);
288         rc = iops->link(old_dentry,dir, dentry);
289         snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 3);
290 exit:
291         snap_trans_commit(cache, handle);
292         RETURN(rc);
293 }
294
295 static int currentfs_symlink(struct inode *dir, struct dentry *dentry, 
296                         const char * symname)
297 {
298         struct snap_cache *cache;
299         int rc;
300         struct inode_operations *iops;
301         void *handle = NULL;
302
303         ENTRY;
304
305         cache = snap_find_cache(dir->i_dev);
306         if (!cache)  
307                 RETURN(-EINVAL);
308
309         handle = snap_trans_start(cache, dir, SNAP_OP_SYMLINK);
310
311         if ( snap_needs_cow(dir) != -1 ) {
312                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
313                 snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 1);
314                 snap_do_cow(dir, get_parent_ino(dir), 0);
315         }
316
317         iops = filter_c2cdiops(cache->cache_filter); 
318         if (!iops || !iops->symlink) 
319                 GOTO(exit, rc = -EINVAL);
320
321         snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 2);
322         rc = iops->symlink(dir, dentry, symname);
323         snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 3);
324         
325 exit:
326         snap_trans_commit(cache, handle);
327         RETURN(rc);
328 }
329
330 static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode, 
331                         int rdev)
332 {
333         struct snap_cache *cache;
334         int rc;
335         struct inode_operations *iops;
336         void *handle = NULL;
337
338         ENTRY;
339
340         if (currentfs_is_under_dotsnap(dentry)) {
341                 RETURN(-EPERM);
342         }
343
344         cache = snap_find_cache(dir->i_dev);
345         if ( !cache ) { 
346                 RETURN(-EINVAL);
347         }
348
349         handle = snap_trans_start(cache, dir, SNAP_OP_MKNOD);
350
351         if ( snap_needs_cow(dir) != -1 ) {
352                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
353                 snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 1);
354                 snap_do_cow(dir, get_parent_ino(dir), 0);
355         }
356
357         iops = filter_c2cdiops(cache->cache_filter); 
358         if (!iops || !iops->mknod) 
359                 GOTO(exit, rc = -EINVAL);
360
361         snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 2);
362         rc = iops->mknod(dir, dentry, mode, rdev);
363         snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 3);
364         
365         /* XXX do we need to set the correct snap_{*}_iops */
366
367 exit:
368         snap_trans_commit(cache, handle);
369         RETURN(rc);
370 }
371
372 static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
373 {
374         struct snap_cache *cache;
375         int rc;
376         struct inode_operations *iops;
377         struct inode *inode = NULL;
378 //      time_t i_ctime = 0;
379         nlink_t i_nlink = 0;
380         off_t   i_size = 0;
381         ino_t ino = 0;
382         int keep_inode = 0;
383 //      struct dentry_operations *save_dop = NULL;
384         void *handle = NULL;
385
386         ENTRY;
387
388         if (currentfs_is_under_dotsnap(dentry)) {
389                 RETURN(-EPERM);
390         }
391
392         cache = snap_find_cache(dir->i_dev);
393         if ( !cache ) { 
394                 RETURN(-EINVAL);
395         }
396
397         handle = snap_trans_start(cache, dir, SNAP_OP_RMDIR);
398
399         if ( snap_needs_cow(dir) != -1 ) {
400                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
401                 snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 1);
402                 snap_do_cow(dir, get_parent_ino(dir), 0);
403         }
404
405         iops = filter_c2cdiops(cache->cache_filter); 
406         if (!iops || !iops->rmdir) 
407                 GOTO(exit, rc = -EINVAL);
408
409         /* XXX : there are two cases that we can't remove this inode from disk. 
410                 1. the inode needs to be cowed. 
411                 2. the inode is a redirector.
412                 then we must keep this inode(dir) so that the inode 
413                 will not be deleted after rmdir, will only remove dentry 
414         */
415
416         if (snap_needs_cow(dentry->d_inode) != -1 || 
417             snap_is_redirector(dentry->d_inode)) {
418                 snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 2);
419                 snap_do_cow (dir, get_parent_ino(dir), SNAP_CREATE_IND_DEL_PRI);
420                 keep_inode = 1;
421         }
422 #if 0
423         if ( keep_inode ) {     
424                 printk("set up dentry ops, before %p\n",dentry->d_op);
425                 save_dop = dentry->d_op;
426
427                 filter_setup_dentry_ops(cache->cache_filter,
428                                 dentry->d_op, &currentfs_dentry_ops);
429                 dentry->d_op = filter_c2udops(cache->cache_filter);
430
431                 printk("set up dentry ops, after %p\n",dentry->d_op);
432
433         }
434
435 #endif
436
437         if( keep_inode && dentry->d_inode ) {
438                 ino = dentry->d_inode->i_ino;
439         //      i_ctime = dentry->d_inode->i_ctime;
440                 i_nlink = dentry->d_inode->i_nlink;
441                 i_size = dentry->d_inode->i_size;
442         }
443
444         snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 4);
445         rc = iops->rmdir(dir, dentry);
446         snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 5);
447
448         /* XXX : check this */
449 #if 0
450         if ( keep_inode ) {
451                 dentry->d_op = save_dop;
452                 printk("restore dentry ops, now at %p\n",dentry->d_op);
453         }
454
455 #endif
456
457         if( keep_inode && ino) {
458                 inode = iget ( dir->i_sb, ino);
459                 if( inode) {
460 //                      inode->i_ctime = i_ctime;
461                         inode->i_nlink = i_nlink;
462                         inode->i_size = i_size;
463                         mark_inode_dirty(inode);
464                         iput( inode);
465 #ifdef CONFIG_SNAPFS_EXT3
466                         /*
467                          * In Ext3, rmdir() will put this inode into
468                          * orphan list, we must remove it out. It's ugly!!
469                          */
470                         if( cache->cache_type == FILTER_FS_EXT3 )
471                                 ext3_orphan_del(handle, inode);
472 #endif
473                         snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 6);
474                 }
475         }
476 exit:
477         snap_trans_commit(cache, handle);
478         EXIT;
479         return rc;
480 }
481
482 static int currentfs_unlink(struct inode *dir, struct dentry *dentry)
483 {
484         struct inode *inode = dentry->d_inode;
485         struct snap_cache *cache;
486         int rc;
487         struct inode_operations *iops;
488         void *handle = NULL;
489
490         ENTRY;
491
492         if (currentfs_is_under_dotsnap(dentry)) {
493                 RETURN(-EPERM);
494         }
495
496         cache = snap_find_cache(dir->i_dev);
497         if ( !cache ) { 
498                 RETURN(-EINVAL);
499         }
500
501         handle = snap_trans_start(cache, dir, SNAP_OP_UNLINK);
502
503         if ( snap_needs_cow(dir) != -1 ) {
504                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
505                 snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 1);
506                 snap_do_cow(dir, get_parent_ino(dir), 0);
507         }
508
509         iops = filter_c2cdiops(cache->cache_filter); 
510         if (!iops || !iops->unlink) {
511                 rc = -EINVAL;
512                 goto exit;
513         }
514
515         /* XXX : if nlink for this inode is 1, there are two cases that we 
516                 can't remove this inode from disk. 
517                 1. the inode needs to be cowed. 
518                 2. the inode is a redirector.
519                 then we increament dentry->d_inode->i_nlink so that the inode 
520                 will not be deleted after unlink, will only remove dentry 
521         */
522
523         if( snap_needs_cow (inode) != -1) {
524                 /* call snap_do_cow with DEL_WITHOUT_IND option */
525                 snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 2);
526                 snap_do_cow(inode, dir->i_ino, SNAP_CREATE_IND_DEL_PRI);
527                 if( inode->i_nlink == 1 )
528                         inode->i_nlink++;
529         } else if (snap_is_redirector (inode) && inode->i_nlink == 1) {
530                 /* call snap_do_cow with DEL_WITH_IND option 
531                  * just free the blocks of inode, not really delete it
532                  */
533                 snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 3);
534                 snap_do_cow (inode, dir->i_ino, SNAP_CREATE_IND_DEL_PRI);
535                 inode->i_nlink++;
536         }
537
538         snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 4);
539         rc = iops->unlink(dir, dentry);
540         snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 5);
541
542 exit:
543         snap_trans_commit(cache, handle);
544         RETURN(rc);
545 }
546
547 static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
548                         struct inode * new_dir, struct dentry *new_dentry)
549 {
550         struct snap_cache *cache;
551         int rc;
552         struct inode_operations *iops;
553         void *handle = NULL;
554
555         ENTRY;
556
557         if (currentfs_is_under_dotsnap(old_dentry) ||
558             currentfs_is_under_dotsnap(new_dentry)) {
559                 RETURN(-EPERM);
560         }
561
562         cache = snap_find_cache(old_dir->i_dev);
563         if ( !cache ) { 
564                 RETURN(-EINVAL);
565         }
566
567         handle = snap_trans_start(cache, old_dir, SNAP_OP_RENAME);
568        
569         /* Always cow the old dir and old dentry->d_inode */ 
570         if ( snap_needs_cow(old_dir) != -1 ) {
571                 CDEBUG(D_INODE, "rename: needs_cow for old_dir %lu\n",old_dir->i_ino);
572                 snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 1);
573                 snap_do_cow(old_dir, get_parent_ino(old_dir), 0);
574         }
575         if( snap_needs_cow (old_dentry->d_inode) != -1) {
576                 CDEBUG(D_INODE, "rename: needs_cow for old_dentry, ino %lu\n",
577                        old_dentry->d_inode->i_ino);
578                 snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 2);
579                 snap_do_cow(old_dentry->d_inode, old_dir->i_ino,0);
580         }
581
582         /* If it's not in the same dir, whether the new_dentry is NULL or not,
583          * we should cow the new_dir. Because rename will use the ino of 
584          * old_dentry as the ino of the new_dentry in new_dir. 
585          */
586         if(( old_dir != new_dir) ) {
587                 if( snap_needs_cow(new_dir) !=-1 ){
588                         CDEBUG(D_INODE, "rename:snap_needs_cow for new_dir %lu\n",
589                                 new_dir->i_ino);
590                         snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,3);
591                         snap_do_cow(new_dir, get_parent_ino(new_dir), 0);       
592                 }
593         }
594
595 #if 0
596         if( ( old_dir != new_dir) && ( new_dentry->d_inode )) {
597                 if(snap_needs_cow(new_dentry->d_inode) !=-1 ){
598                         printk("rename:needs_cow for new_entry ,ino %lu\n",
599                                 new_dentry->d_inode->i_ino);
600                         snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 4);
601                         snap_do_cow (new_dentry->d_inode, 
602                                 new_dentry->d_parent->d_inode->i_ino, 0);       
603                 }
604         }
605 #endif
606         /* The inode for the new_dentry will be freed for normal rename option.
607          * But we should keep this inode since we need to keep it available 
608          * for the clone and for snap rollback
609          */
610         if( new_dentry->d_inode && new_dentry->d_inode->i_nlink == 1 ) {
611                 if( snap_needs_cow (new_dentry->d_inode) != -1) {
612                         /* call snap_do_cow with DEL_WITHOUT_IND option */
613                         snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,4);
614                         snap_do_cow(new_dentry->d_inode, new_dir->i_ino,
615                                     SNAP_CREATE_IND_DEL_PRI);
616                         new_dentry->d_inode->i_nlink++;
617                 }
618                 else if( snap_is_redirector (new_dentry->d_inode) ) {
619                         /* call snap_do_cow with DEL_WITH_IND option 
620                          * just free the blocks of inode, not really delete it
621                          */
622                         snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,4);
623                         snap_do_cow (new_dentry->d_inode, new_dir->i_ino, 
624                                      SNAP_CREATE_IND_DEL_PRI);
625                         new_dentry->d_inode->i_nlink++;
626                 }       
627         }
628
629         iops = filter_c2cdiops(cache->cache_filter); 
630         if (!iops || !iops->rename) {
631                 rc = -EINVAL;
632                 goto exit;
633         }
634
635         snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 5);
636         rc = iops->rename(old_dir, old_dentry, new_dir, new_dentry);
637         snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 6);
638
639 exit:
640         snap_trans_commit(cache, handle);
641         RETURN(rc);
642 }
643
644 static int currentfs_readdir(struct file *filp, void *dirent,
645                              filldir_t filldir)
646 {
647         struct snap_cache *cache;
648         struct file_operations *fops;
649         int rc;
650         
651         ENTRY;
652         if( !filp || !filp->f_dentry || !filp->f_dentry->d_inode ) {
653                 RETURN(-EINVAL);
654         }
655
656         cache = snap_find_cache(filp->f_dentry->d_inode->i_dev);
657         if ( !cache ) { 
658                 RETURN(-EINVAL);
659         }
660         fops = filter_c2cdfops( cache->cache_filter );
661         if( !fops ) {
662                 RETURN(-EINVAL);
663         }
664
665         /*
666          * no action if we are under clonefs or .snap
667          */
668         if( cache->cache_show_dotsnap &&
669             (filp->f_dentry->d_sb == cache->cache_sb) &&
670             !currentfs_is_under_dotsnap(filp->f_dentry) ){
671                 if( filp->f_pos == 0 ){
672                         if( filldir(dirent, ".snap",
673                                     strlen(".snap")+1, filp->f_pos,
674                                     -1, 0) ){
675                                 return -EINVAL;
676                         }
677                         filp->f_pos += strlen(".snap")+1;
678                 }
679                 filp->f_pos -= strlen(".snap")+1;
680                 rc = fops->readdir(filp, dirent, filldir);
681                 filp->f_pos += strlen(".snap")+1;
682         }else
683                 rc = fops->readdir(filp, dirent, filldir);
684
685         RETURN(rc);
686 }
687
688 struct file_operations currentfs_dir_fops = {
689         readdir: currentfs_readdir
690 };
691
692 struct inode_operations currentfs_dir_iops = { 
693         create:         currentfs_create,
694         mkdir:          currentfs_mkdir,
695         link:           currentfs_link,
696         symlink:        currentfs_symlink,
697         mknod:          currentfs_mknod,
698         rmdir:          currentfs_rmdir,
699         unlink:         currentfs_unlink,
700         rename:         currentfs_rename,
701         lookup:         currentfs_lookup
702 };