Whamcloud - gitweb
add .cvsignore
[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         EXIT;
147 }
148
149 static int clonefs_statfs(struct super_block *sb, struct statfs *buf) 
150 {
151         struct snap_clone_info *clone_sb;
152         struct snap_cache *cache; 
153
154         ENTRY;
155         clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
156
157         cache = clone_sb->clone_cache;
158         if (!cache) {
159                 CERROR("clone_statfs: no cache\n");
160                 RETURN(-EINVAL);
161         }
162
163         return cache->cache_filter->o_caops.cache_sops->statfs
164                 (cache->cache_sb, buf);
165 }
166
167 struct super_operations clone_super_ops =
168 {
169         read_inode:     clonefs_read_inode,     /* read_inode */
170         put_super:      clonefs_put_super,      /* put_super */
171         statfs:         clonefs_statfs,         /* statfs */
172 };
173
174
175 /* ***************** end of clonefs super ops *******************  */ 
176 /* ***************** begin clonefs dir ops *******************  */ 
177
178 static void d_unalloc(struct dentry *dentry)
179 {
180
181         list_del(&dentry->d_hash);
182         INIT_LIST_HEAD(&dentry->d_hash);
183         dput(dentry); /* this will free the dentry memory */
184 }
185
186 /*
187  * Return the underlying fs dentry with name in 'dentry' that points
188  * to the right inode. 'dir' is the clone fs directory to search for
189  * the 'dentry'.
190  */
191 struct dentry *clonefs_lookup(struct inode *dir,  struct dentry *dentry)
192 {
193         struct inode            *cache_dir = NULL;
194         struct dentry           *cache_dentry = NULL, *tmp = NULL;
195         struct inode            *cache_inode;
196         struct dentry           *result;
197         struct inode            *inode;
198         struct snap_clone_info  *clone_sb;
199
200         ENTRY;
201
202         cache_dir = clonefs_get_inode(dir); 
203         if (!cache_dir) 
204                 RETURN(ERR_PTR(-ENOENT));
205                 
206         tmp = dget(list_entry(cache_dir->i_dentry.next, struct dentry, d_alias));
207
208         cache_dentry = d_alloc(tmp->d_parent, &dentry->d_name);
209         
210         if (!cache_dentry) {
211                 iput(cache_dir);
212                 dput(tmp);
213                 RETURN(ERR_PTR(-ENOENT));
214         }
215
216         /* Lock cache directory inode. */
217         down(&cache_dir->i_sem);
218         dput(tmp);
219         /*
220          * Call underlying fs lookup function to set the 'd_inode' pointer
221          * to the corresponding directory inode.
222          *
223          * Note: If the lookup function does not return NULL, return
224          * from 'clone_lookup' with an error.
225          */
226         result = cache_dir->i_op->lookup(cache_dir, cache_dentry);
227         if (result) { 
228                 dput(cache_dentry);
229                 up(&cache_dir->i_sem);
230                 iput(cache_dir);
231                 dentry->d_inode = NULL;
232                 RETURN(ERR_PTR(-ENOENT));
233         }
234         /* Unlock cache directory inode. */
235         up(&cache_dir->i_sem);
236
237         /*
238          * If there is no inode pointer in the underlying fs 'cache_dentry'
239          * then the directory doesn't have an entry with this name.  In fs/ext2
240          * we see that we return 0 and put dentry->d_inode = NULL;
241          */
242         cache_inode = cache_dentry->d_inode;
243         if ( cache_inode == NULL ) {
244                 inode = NULL;
245         } else {
246                 clone_sb = (struct snap_clone_info *) &dir->i_sb->u.generic_sbp;
247                 /* note, iget below will follow a redirector, since 
248                    it calls into clone_read_inode 
249                 */ 
250                 inode = iget(dir->i_sb, cache_inode->i_ino);
251         }
252
253         /* dput(cache_dentry) will not put the dentry away
254          * immediately, unless we first arrange that its hash list is
255          * empty.
256          */
257
258         if ( cache_inode != NULL ) {
259                 CDEBUG(D_INODE, "cache ino %ld, count %d, dir %ld, count %d\n", 
260                        cache_inode->i_ino, atomic_read(&cache_inode->i_count), 
261                        cache_dir->i_ino, atomic_read(&cache_dir->i_count));
262         }
263
264         d_unalloc(cache_dentry);
265         iput(cache_dir);
266
267         /*
268          * Add 'inode' to the directory entry 'dentry'.
269          */
270         d_add(dentry, inode);
271
272         RETURN(NULL);
273 }
274
275
276 /* instantiate a file handle to the cache file */
277 static void clonefs_prepare_snapfile(struct inode *i,
278                                      struct file *clone_file, 
279                                      struct inode *cache_inode,
280                                      struct file *cache_file,
281                                      struct dentry *cache_dentry)
282 {
283         ENTRY;
284         
285         cache_file->f_pos = clone_file->f_pos;
286         cache_file->f_mode = clone_file->f_mode;
287         cache_file->f_flags = clone_file->f_flags;
288         cache_file->f_count  = clone_file->f_count;
289         cache_file->f_owner  = clone_file->f_owner;
290         cache_file->f_op = cache_inode->i_fop;
291         cache_file->f_dentry = cache_dentry;
292         cache_file->f_dentry->d_inode = cache_inode;
293         
294         EXIT;
295 }
296
297 /* update the clonefs file struct after IO in cache file */
298 static void clonefs_restore_snapfile(struct inode *cache_inode,
299                                    struct file *cache_file, 
300                                    struct inode *clone_inode,
301                                    struct file *clone_file)
302 {
303         ENTRY;
304  
305         cache_file->f_pos = clone_file->f_pos;
306         cache_inode->i_size = clone_inode->i_size;
307         
308         EXIT;
309 }
310
311 static int clonefs_readdir(struct file *file, void *dirent, 
312                            filldir_t filldir)
313 {
314         int result;
315         struct inode *cache_inode;
316         struct file open_file;
317         struct dentry open_dentry;
318         struct inode *inode = file->f_dentry->d_inode;
319
320         ENTRY;
321
322         if(!inode) {
323                 RETURN(-EINVAL);
324         }
325         cache_inode = clonefs_get_inode(inode);
326
327         if (!cache_inode) {
328                 make_bad_inode(inode);
329                 RETURN(-ENOMEM);
330         }
331
332         CDEBUG(D_INODE,"clone ino %ld\n",cache_inode->i_ino);
333
334         clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
335                               &open_dentry);
336         /* potemkin case: we are handed a directory inode */
337         result = -ENOENT;
338         if (open_file.f_op->readdir) {
339                 down(&cache_inode->i_sem);
340                 result = open_file.f_op->readdir(&open_file, dirent, filldir);
341                 up(&cache_inode->i_sem);
342         }
343         clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
344         iput(cache_inode);
345         RETURN(result);
346 }
347
348 struct file_operations clonefs_dir_file_ops = {
349         readdir:        clonefs_readdir,        /* readdir */
350 };
351
352 struct inode_operations clonefs_dir_inode_ops = {
353         lookup:         clonefs_lookup,   /* lookup */
354 };
355
356
357 /* ***************** end of clonefs dir ops *******************  */ 
358 /* ***************** begin clonefs file ops *******************  */ 
359
360 static int clonefs_readpage(struct file *file, struct page *page)
361 {
362         int result = 0;
363         struct inode *cache_inode;
364         struct file open_file;
365         struct dentry open_dentry;
366         struct inode *inode;
367
368         ENTRY;
369
370         inode = file->f_dentry->d_inode;
371         cache_inode = clonefs_get_inode(file->f_dentry->d_inode); 
372         if (!cache_inode) {
373                 make_bad_inode(file->f_dentry->d_inode);
374                 RETURN(-ENOMEM);
375         }
376
377         clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
378                               &open_dentry);
379         /* tell currentfs_readpage the primary inode number */
380         open_dentry.d_fsdata = (void*)inode->i_ino;
381
382         /* potemkin case: we are handed a directory inode */
383         down(&cache_inode->i_sem);
384         /* XXX - readpage NULL on directories... */
385         result = cache_inode->i_mapping->a_ops->readpage(&open_file, page);
386
387         up(&cache_inode->i_sem);
388         clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
389         iput(cache_inode);
390         RETURN(result);
391 }
392
393 struct file_operations clonefs_file_file_ops = {
394         read:   generic_file_read,      /* read -- bad */
395         mmap:   generic_file_mmap,      /* mmap */
396 };
397
398 struct address_space_operations clonefs_file_address_ops = {
399         readpage:       clonefs_readpage
400 };
401
402
403 /* ***************** end of clonefs file ops *******************  */ 
404 /* ***************** begin clonefs symlink ops *******************  */ 
405
406 static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
407 {
408         int res;
409         struct inode * cache_inode;
410         struct inode * old_inode;
411
412         ENTRY;
413
414         cache_inode = clonefs_get_inode(dentry->d_inode); 
415
416         res = -ENOENT;
417
418         if ( ! cache_inode ) {
419                 CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
420                 RETURN(res);    
421         }
422         
423         /* XXX: shall we allocate a new dentry ? 
424                 The following is safe for ext3, etc. because ext2_readlink only
425                 use the inode info */
426
427         /* save the old dentry inode */ 
428         old_inode = dentry->d_inode;
429         /* set dentry inode to cache inode */
430         dentry->d_inode = cache_inode;
431
432         if ( cache_inode->i_op->readlink ) {
433                 res = cache_inode->i_op->readlink(dentry, buf, len); 
434         }else {
435                 CDEBUG(D_INODE,"NO readlink for ino %lu\n", cache_inode->i_ino);
436         }
437
438         /* restore the old inode */
439         dentry->d_inode = old_inode;
440
441         iput(cache_inode);
442
443         RETURN(res);
444 }
445
446 static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
447 {
448         struct inode * cache_inode;
449         struct inode * old_inode;
450         int    res;
451
452         ENTRY;
453
454         cache_inode = clonefs_get_inode(dentry->d_inode); 
455         if ( ! cache_inode ) {
456                 CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
457                 RETURN(-ENOENT);        
458         }
459
460         /* XXX: shall we allocate a new dentry ? 
461                 The following is safe for ext2, etc. because ext2_follow_link 
462                 only use the inode info */
463
464         /* save the old dentry inode */ 
465         old_inode = dentry->d_inode;
466         /* set dentry inode to cache inode */
467         dentry->d_inode = cache_inode;
468
469         if ( cache_inode->i_op->follow_link ) {
470                 res = cache_inode->i_op->follow_link(dentry, nd); 
471         }
472
473         /* restore the old inode */
474         dentry->d_inode = old_inode;
475
476         iput(cache_inode);
477
478         RETURN(res);
479 }
480
481 struct inode_operations clonefs_symlink_inode_ops =
482 {
483         /*FIXME later getxattr, listxattr, 
484          * other method need to be replaced too 
485          * */  
486         readlink:       clonefs_readlink,   /* readlink */              
487         follow_link:    clonefs_follow_link,/* follow_link */             
488 };
489
490