Whamcloud - gitweb
1ef807807698b09a80f7d60d8186466672466ce2
[fs/lustre-release.git] / lustre / snapfs / clonefs.c
1 /*
2  * Super block/filesystem wide operations
3  *
4  * Copryright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and
5  * Michael Callahan <callahan@maths.ox.ac.uk>
6  *
7  * Rewritten for Linux 2.1.  Peter Braam <braam@cs.cmu.edu>
8  * Copyright (C) Carnegie Mellon University
9  * 
10  * Copyright (C) 2000, Mountain View Data, Inc, authors
11  * Peter Braam <braam@mountainviewdata.com>, 
12  * Harrison Xing <harrisonx@mountainviewdata.com>
13  * 
14  */
15
16 #define __NO_VERSION__
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/mm.h>
20 #include <linux/string.h>
21 #include <linux/stat.h>
22 #include <linux/errno.h>
23 #include <linux/locks.h>
24 #include <linux/unistd.h>
25
26 #include <asm/system.h>
27 #include <asm/uaccess.h>
28
29 #include <linux/fs.h>
30 #include <linux/stat.h>
31 #include <linux/errno.h>
32 #include <linux/locks.h>
33 #include <linux/string.h>
34 #include <asm/uaccess.h>
35 #include <linux/malloc.h>
36 #include <linux/vmalloc.h>
37 #include <asm/segment.h>
38
39 #include <linux/filter.h>
40 #include <linux/snapfs.h>
41 #include <linux/snapsupport.h>
42
43 /* Clone is a simple file system, read only that just follows redirectors
44    we have placed the entire implementation except clone_read_super in
45    this file 
46  */
47
48 struct inode_operations clonefs_dir_inode_operations;
49 struct inode_operations clonefs_file_inode_operations;
50 struct inode_operations clonefs_symlink_inode_operations;
51 struct inode_operations clonefs_special_inode_operations;
52 struct file_operations clonefs_dir_file_operations;
53 struct file_operations clonefs_file_file_operations;
54 struct file_operations clonefs_special_file_operations;
55
56 /* support routines for following redirectors */
57
58 /* Parameter is clonefs inode, 'inode', and typically this may be
59    called before read_inode has completed on this clonefs inode,
60    i.e. we may only assume that i_ino is valid.
61
62    We return an underlying (likely disk) fs inode.  This involved
63    handling any redirector inodes found along the way. 
64
65    This function is used by all clone fs interface functions to get an
66    underlying fs inode.  
67 */
68
69 struct inode *clonefs_get_inode(struct inode *inode)
70 {
71         struct snap_clone_info *clone_sb;
72         struct inode *cache_inode, *redirected_inode;
73
74         ENTRY;
75
76         /* this only works if snapfs_current does NOT overwrite read_inode */
77         clone_sb = (struct snap_clone_info *) &inode->i_sb->u.generic_sbp;
78
79         /* basic invariant: clone and current ino's are equal */
80         cache_inode = iget(clone_sb->clone_cache->cache_sb, inode->i_ino); 
81
82         redirected_inode = snap_redirect(cache_inode, inode->i_sb);
83
84         CDEBUG(D_SNAP, "redirected_inode: %lx, cache_inode %lx\n",
85                (ulong) redirected_inode, (ulong) cache_inode);
86
87         CDEBUG(D_SNAP, "cache_inode: %lx, ino %ld, sb %lx, count %d\n",
88                (ulong) cache_inode, cache_inode->i_ino, 
89                (ulong) cache_inode->i_sb, cache_inode->i_count);
90
91         iput(cache_inode); 
92         EXIT;
93         return redirected_inode;
94 }
95
96
97 /* super operations */
98 static void clonefs_read_inode(struct inode *inode)
99 {
100         struct inode *cache_inode;
101
102         ENTRY;
103
104         CDEBUG(D_SNAP, "inode: %lx, ino %ld, sb %lx, count %d\n",
105                (ulong) inode , inode->i_ino, (long) inode->i_sb, 
106                inode->i_count);
107
108         /* redirecting inode in the cache */
109         cache_inode = clonefs_get_inode(inode);
110         if (!cache_inode) {
111                 make_bad_inode(inode);
112                 EXIT;
113                 return;
114         }
115         /* copy attrs of that inode to our clone inode */
116         snapfs_cpy_attrs(inode, cache_inode);
117
118         if (S_ISREG(inode->i_mode))
119                 inode->i_op = &clonefs_file_inode_operations;
120         else if (S_ISDIR(inode->i_mode))
121                 inode->i_op = &clonefs_dir_inode_operations;
122         else if (S_ISLNK(inode->i_mode))
123                 inode->i_op = &clonefs_symlink_inode_operations;
124         else if (S_ISCHR(inode->i_mode))
125                 inode->i_op = &chrdev_inode_operations;
126         else if (S_ISBLK(inode->i_mode))
127                 inode->i_op = &blkdev_inode_operations;
128         else if (S_ISFIFO(inode->i_mode))
129                 init_fifo(inode);
130
131         iput(cache_inode);
132
133         CDEBUG(D_SNAP, "cache_inode: %lx ino %ld, sb %lx, count %d\n",
134                 (ulong) cache_inode, cache_inode->i_ino, 
135                (ulong) cache_inode->i_sb, cache_inode->i_count);
136         EXIT;
137         return; 
138 }
139
140
141 static void clonefs_put_super(struct super_block *sb)
142 {
143         struct snap_clone_info *clone_sb;
144
145         ENTRY;
146         CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
147                 (ulong) sb, (ulong) &sb->u.generic_sbp);
148         clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
149         dput( clone_sb->clone_cache->cache_sb->s_root );
150         list_del(&clone_sb->clone_list_entry);
151
152         MOD_DEC_USE_COUNT;
153
154         EXIT;
155 }
156
157 static int clonefs_statfs(struct super_block *sb, struct statfs *buf, 
158                         int bufsiz)
159 {
160         struct snap_clone_info *clone_sb;
161         struct snap_cache *cache; 
162
163         ENTRY;
164         clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
165
166         cache = clone_sb->clone_cache;
167         if (!cache) {
168                 printk("clone_statfs: no cache\n");
169                 return -EINVAL;
170         }
171
172         EXIT;
173         return cache->cache_filter->o_caops.cache_sops->statfs
174                 (cache->cache_sb, buf, bufsiz);
175 }
176
177 struct super_operations clone_super_ops =
178 {
179         clonefs_read_inode,       /* read_inode */
180         NULL,                   /* write_inode */
181         NULL,                   /* put_inode */
182         NULL,                   /* delete_inode */
183         NULL,                   /* notify_change */
184         clonefs_put_super,      /* put_super */
185         NULL,                   /* write_super */
186         clonefs_statfs,         /* statfs */
187         NULL                    /* remount_fs */
188 };
189
190
191 /* ***************** end of clonefs super ops *******************  */ 
192 /* ***************** begin clonefs dir ops *******************  */ 
193
194 static void d_unalloc(struct dentry *dentry)
195 {
196
197         list_del(&dentry->d_hash);
198         INIT_LIST_HEAD(&dentry->d_hash);
199         dput(dentry); /* this will free the dentry memory */
200 }
201
202 /*
203  * Return the underlying fs dentry with name in 'dentry' that points
204  * to the right inode. 'dir' is the clone fs directory to search for
205  * the 'dentry'.
206  */
207 struct dentry *clonefs_lookup(struct inode *dir,  struct dentry *dentry)
208 {
209         struct inode            *cache_dir;
210         struct dentry           *cache_dentry;
211         struct inode            *cache_inode;
212         struct dentry           *result;
213         struct inode            *inode;
214         struct snap_clone_info  *clone_sb;
215
216         ENTRY;
217
218         cache_dir = clonefs_get_inode(dir); 
219
220         cache_dentry = d_alloc(dentry->d_parent, &dentry->d_name);
221         if (!cache_dentry) {
222                 iput(cache_dir);
223                 EXIT;
224                 return ERR_PTR(-ENOENT);
225         }
226
227         /* Lock cache directory inode. */
228         down(&cache_dir->i_sem);
229         /*
230          * Call underlying fs lookup function to set the 'd_inode' pointer
231          * to the corresponding directory inode.
232          *
233          * Note: If the lookup function does not return NULL, return
234          * from 'clone_lookup' with an error.
235          */
236         result = cache_dir->i_op->lookup(cache_dir, cache_dentry);
237         if (result) { 
238                 dput(cache_dentry);
239                 up(&cache_dir->i_sem);
240                 iput(cache_dir);
241                 dentry->d_inode = NULL;
242                 EXIT;
243                 return ERR_PTR(-ENOENT);
244         }
245         /* Unlock cache directory inode. */
246         up(&cache_dir->i_sem);
247
248         /*
249          * If there is no inode pointer in the underlying fs 'cache_dentry'
250          * then the directory doesn't have an entry with this name.  In fs/ext2
251          * we see that we return 0 and put dentry->d_inode = NULL;
252          */
253         cache_inode = cache_dentry->d_inode;
254         if ( cache_inode == NULL ) {
255                 inode = NULL;
256         } else {
257                 clone_sb = (struct snap_clone_info *) &dir->i_sb->u.generic_sbp;
258                 /* note, iget below will follow a redirector, since 
259                    it calls into clone_read_inode 
260                 */ 
261                 inode = iget(dir->i_sb, cache_inode->i_ino);
262         }
263
264         /* dput(cache_dentry) will not put the dentry away
265          * immediately, unless we first arrange that its hash list is
266          * empty.
267          */
268
269         if ( cache_inode != NULL ) {
270                 CDEBUG(D_INODE, "cache ino %ld, count %d, dir %ld, count %d\n", 
271                                 cache_inode->i_ino, cache_inode->i_count, cache_dir->i_ino, 
272                                 cache_dir->i_count);
273         }
274
275         d_unalloc(cache_dentry);
276         iput(cache_dir);
277
278         /*
279          * Add 'inode' to the directory entry 'dentry'.
280          */
281         d_add(dentry, inode);
282
283         EXIT;
284         return NULL;
285 }
286
287
288 /* instantiate a file handle to the cache file */
289 static void clonefs_prepare_snapfile(struct inode *i,
290                                      struct file *clone_file, 
291                                      struct inode *cache_inode,
292                                      struct file *cache_file,
293                                      struct dentry *cache_dentry)
294 {
295         ENTRY;
296         cache_file->f_pos = clone_file->f_pos;
297         cache_file->f_mode = clone_file->f_mode;
298         cache_file->f_flags = clone_file->f_flags;
299         cache_file->f_count  = clone_file->f_count;
300         cache_file->f_owner  = clone_file->f_owner;
301         cache_file->f_op = cache_inode->i_op->default_file_ops;
302         cache_file->f_dentry = cache_dentry;
303         cache_file->f_dentry->d_inode = cache_inode;
304         EXIT;
305         return ;
306 }
307
308 /* update the clonefs file struct after IO in cache file */
309 static void clonefs_restore_snapfile(struct inode *cache_inode,
310                                    struct file *cache_file, 
311                                    struct inode *clone_inode,
312                                    struct file *clone_file)
313 {
314         ENTRY;
315         cache_file->f_pos = clone_file->f_pos;
316         cache_inode->i_size = clone_inode->i_size;
317         EXIT;
318         return;
319 }
320
321 static int clonefs_readdir(struct file *file, void *dirent, 
322                            filldir_t filldir)
323 {
324         int result;
325         struct inode *cache_inode;
326         struct file open_file;
327         struct dentry open_dentry;
328         struct inode *inode=file->f_dentry->d_inode;
329
330         ENTRY;
331
332         if(!inode) {
333                 EXIT;
334                 return -EINVAL;
335         }
336         cache_inode = clonefs_get_inode(inode);
337
338         if (!cache_inode) {
339                 make_bad_inode(inode);
340                 EXIT;
341                 return -ENOMEM;
342         }
343
344         CDEBUG(D_INODE,"clone ino %ld\n",cache_inode->i_ino);
345
346         clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
347                               &open_dentry);
348         /* potemkin case: we are handed a directory inode */
349         result = -ENOENT;
350         if (open_file.f_op->readdir) {
351                 down(&cache_inode->i_sem);
352                 result = open_file.f_op->readdir(&open_file, dirent, filldir);
353                 up(&cache_inode->i_sem);
354         }
355         clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
356         iput(cache_inode);
357         EXIT;
358         return result;
359 }
360
361 struct file_operations clonefs_dir_file_operations = {
362         NULL,                   /* lseek */
363         NULL,                   /* read -- bad */
364         NULL,                   /* write */
365         clonefs_readdir,        /* readdir */
366         NULL,                   /* select */
367         NULL,                   /* ioctl */
368         NULL,                   /* mmap */
369         NULL,                   /* open */
370         NULL,
371         NULL,                   /* release */
372         NULL,                   /* fsync */
373         NULL,                   
374         NULL,
375         NULL
376 };
377
378 struct inode_operations clonefs_dir_inode_operations =
379 {
380         &clonefs_dir_file_operations,
381         NULL,           /* create */
382         clonefs_lookup,   /* lookup */
383         NULL,           /* link */
384         NULL,           /* unlink */
385         NULL,           /* symlink */
386         NULL,           /* mkdir */
387         NULL,           /* rmdir */
388         NULL,           /* mknod */
389         NULL,           /* rename */
390         NULL,           /* readlink */
391         NULL,           /* follow_link */
392         NULL,           /* readpage */
393         NULL,           /* writepage */
394         NULL,           /* bmap */
395         NULL,           /* truncate */
396         NULL,           /* permission */
397         NULL,           /* smap */
398         NULL,           /* update page */
399         NULL,           /* revalidate */
400 };
401
402
403 /* ***************** end of clonefs dir ops *******************  */ 
404 /* ***************** begin clonefs file ops *******************  */ 
405
406 int clonefs_readpage(struct file *file, struct page *page)
407 {
408         int result = 0;
409         struct inode *cache_inode;
410         struct file open_file;
411         struct dentry open_dentry;
412         struct inode *inode;
413
414         ENTRY;
415
416         inode = file->f_dentry->d_inode;
417         cache_inode = clonefs_get_inode(file->f_dentry->d_inode); 
418         if (!cache_inode) {
419                 make_bad_inode(file->f_dentry->d_inode);
420                 EXIT;
421                 return -ENOMEM;
422         }
423
424         clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
425                               &open_dentry);
426         /* tell currentfs_readpage the primary inode number */
427         open_dentry.d_fsdata = (void*)inode->i_ino;
428
429         /* potemkin case: we are handed a directory inode */
430         down(&cache_inode->i_sem);
431         /* XXX - readpage NULL on directories... */
432         if (cache_inode->i_op->readpage == NULL)
433                 printk("Yes, Grigori, directories are a problem.\n");
434         else
435                 cache_inode->i_op->readpage(&open_file, page);
436         up(&cache_inode->i_sem);
437         clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
438         iput(cache_inode);
439         EXIT;
440         return result;
441 }
442
443
444 struct file_operations clonefs_file_file_operations = {
445         NULL,                   /* lseek */
446         generic_file_read,      /* read -- bad */
447         NULL,                   /* write */
448         NULL,                   /* readdir */
449         NULL,                   /* select */
450         NULL,                   /* ioctl */
451         generic_file_mmap,      /* mmap */
452         NULL,                   /* open */
453         NULL,
454         NULL,                   /* release */
455         NULL,                   /* fsync */
456         NULL,                   
457         NULL,
458         NULL
459 };
460
461 struct inode_operations clonefs_file_inode_operations =
462 {
463         &clonefs_file_file_operations,
464         NULL,           /* create */
465         NULL,           /* lookup */
466         NULL,           /* link */
467         NULL,           /* unlink */
468         NULL,           /* symlink */
469         NULL,           /* mkdir */
470         NULL,           /* rmdir */
471         NULL,           /* mknod */
472         NULL,           /* rename */
473         NULL,           /* readlink */
474         NULL,           /* follow_link */
475         clonefs_readpage, /* readpage */
476         NULL,           /* writepage */
477         NULL,           /* bmap */
478         NULL,           /* truncate */
479         NULL,           /* permission */
480         NULL,           /* smap */
481         NULL,           /* update page */
482         NULL,           /* revalidate */
483 };
484
485
486
487 /* ***************** end of clonefs file ops *******************  */ 
488 /* ***************** begin clonefs symlink ops *******************  */ 
489
490 int clonefs_readlink(struct dentry *dentry, char *buf, int len)
491 {
492         int res;
493         struct inode * cache_inode;
494         struct inode * old_inode;
495
496         ENTRY;
497
498         cache_inode = clonefs_get_inode(dentry->d_inode); 
499
500         res = -ENOENT;
501
502         if ( ! cache_inode ) {
503                 CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
504                 EXIT;
505                 return res;     
506         }
507         
508         /* XXX: shall we allocate a new dentry ? 
509                 The following is safe for ext2, etc. because ext2_readlink only
510                 use the inode info */
511
512         /* save the old dentry inode */ 
513         old_inode = dentry->d_inode;
514         /* set dentry inode to cache inode */
515         dentry->d_inode = cache_inode;
516
517         if ( cache_inode->i_op->readlink ) {
518                 res = cache_inode->i_op->readlink(dentry, buf, len); 
519         }else {
520                 CDEBUG(D_INODE,"NO readlink for ino %lu\n", cache_inode->i_ino);
521         }
522
523         /* restore the old inode */
524         dentry->d_inode = old_inode;
525
526         iput(cache_inode);
527
528         EXIT;
529         return res;
530 }
531
532 struct dentry * clonefs_follow_link(struct dentry * dentry,
533                                         struct dentry *base,
534                                         unsigned int follow)
535 {
536         struct dentry * res;
537         struct inode * cache_inode;
538         struct inode * old_inode;
539
540         ENTRY;
541         res = ERR_PTR(-ENOENT);
542
543         cache_inode = clonefs_get_inode(dentry->d_inode); 
544         if ( ! cache_inode ) {
545                 CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
546                 EXIT;
547                 return res;     
548         }
549
550         /* XXX: shall we allocate a new dentry ? 
551                 The following is safe for ext2, etc. because ext2_follow_link 
552                 only use the inode info */
553
554         /* save the old dentry inode */ 
555         old_inode = dentry->d_inode;
556         /* set dentry inode to cache inode */
557         dentry->d_inode = cache_inode;
558
559         if ( cache_inode->i_op->follow_link ) {
560                 res = cache_inode->i_op->follow_link(dentry, base, follow); 
561         }
562
563         /* restore the old inode */
564         dentry->d_inode = old_inode;
565
566         iput(cache_inode);
567
568         EXIT;
569         return res;
570 }
571
572 struct inode_operations clonefs_symlink_inode_operations =
573 {
574         NULL,               /* no file operations */      
575         NULL,               /* create */                  
576         NULL,               /* lookup */                  
577         NULL,               /* link */                    
578         NULL,               /* unlink */                  
579         NULL,               /* symlink */                 
580         NULL,               /* mkdir */                   
581         NULL,               /* rmdir */                   
582         NULL,               /* mknod */                   
583         NULL,               /* rename */                  
584         clonefs_readlink,   /* readlink */              
585         clonefs_follow_link,/* follow_link */             
586         NULL,               /* readpage */                
587         NULL,               /* writepage */               
588         NULL,               /* bmap */                    
589         NULL,               /* truncate */                
590         NULL,               /* permission */              
591         NULL,               /* smap */                    
592         NULL,               /* update page */             
593         NULL,               /* revalidate */          
594 };
595
596