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