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 / 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 static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
187 {
188         atomic_set(&dentry->d_count, 1);
189         dentry->d_vfs_flags = 0;
190         dentry->d_flags = 0;
191         dentry->d_inode = inode;
192         dentry->d_op = NULL;
193         dentry->d_fsdata = NULL;
194         dentry->d_mounted = 0;
195         INIT_LIST_HEAD(&dentry->d_hash);
196         INIT_LIST_HEAD(&dentry->d_lru);
197         INIT_LIST_HEAD(&dentry->d_subdirs);
198         INIT_LIST_HEAD(&dentry->d_alias);
199 }
200 /*
201  * Return the underlying fs dentry with name in 'dentry' that points
202  * to the right inode. 'dir' is the clone fs directory to search for
203  * the 'dentry'.
204  */
205 struct dentry *clonefs_lookup(struct inode *dir,  struct dentry *dentry)
206 {
207         struct inode            *cache_dir = NULL;
208         struct dentry           *cache_dentry = NULL; 
209         struct inode            *cache_inode;
210         struct dentry           *result;
211         struct dentry           tmp;
212         struct inode            *inode;
213         struct snap_clone_info  *clone_sb;
214
215         ENTRY;
216
217         cache_dir = clonefs_get_inode(dir); 
218         if (!cache_dir) 
219                 RETURN(ERR_PTR(-ENOENT));
220         /*FIXME later, we make parent dentry here
221          *there may some problems in lookup
222          */      
223         prepare_parent_dentry(&tmp, cache_dir);
224         cache_dentry = d_alloc(&tmp, &dentry->d_name);
225         
226         if (!cache_dentry) {
227                 iput(cache_dir);
228                 RETURN(ERR_PTR(-ENOENT));
229         }
230
231         /* Lock cache directory inode. */
232         down(&cache_dir->i_sem);
233         /*
234          * Call underlying fs lookup function to set the 'd_inode' pointer
235          * to the corresponding directory inode.
236          *
237          * Note: If the lookup function does not return NULL, return
238          * from 'clone_lookup' with an error.
239          */
240         result = cache_dir->i_op->lookup(cache_dir, cache_dentry);
241         if (result) { 
242                 dput(cache_dentry);
243                 up(&cache_dir->i_sem);
244                 iput(cache_dir);
245                 dentry->d_inode = NULL;
246                 RETURN(ERR_PTR(-ENOENT));
247         }
248         /* Unlock cache directory inode. */
249         up(&cache_dir->i_sem);
250
251         /*
252          * If there is no inode pointer in the underlying fs 'cache_dentry'
253          * then the directory doesn't have an entry with this name.  In fs/ext2
254          * we see that we return 0 and put dentry->d_inode = NULL;
255          */
256         cache_inode = cache_dentry->d_inode;
257         if ( cache_inode == NULL ) {
258                 inode = NULL;
259         } else {
260                 clone_sb = (struct snap_clone_info *) &dir->i_sb->u.generic_sbp;
261                 /* note, iget below will follow a redirector, since 
262                    it calls into clone_read_inode 
263                 */ 
264                 inode = iget(dir->i_sb, cache_inode->i_ino);
265         }
266
267         /* dput(cache_dentry) will not put the dentry away
268          * immediately, unless we first arrange that its hash list is
269          * empty.
270          */
271
272         if ( cache_inode != NULL ) {
273                 CDEBUG(D_INODE, "cache ino %ld, count %d, dir %ld, count %d\n", 
274                        cache_inode->i_ino, atomic_read(&cache_inode->i_count), 
275                        cache_dir->i_ino, atomic_read(&cache_dir->i_count));
276         }
277
278         d_unalloc(cache_dentry);
279         iput(cache_dir);
280
281         /*
282          * Add 'inode' to the directory entry 'dentry'.
283          */
284         d_add(dentry, inode);
285
286         RETURN(NULL);
287 }
288
289
290 /* instantiate a file handle to the cache file */
291 static void clonefs_prepare_snapfile(struct inode *i,
292                                      struct file *clone_file, 
293                                      struct inode *cache_inode,
294                                      struct file *cache_file,
295                                      struct dentry *cache_dentry)
296 {
297         ENTRY;
298         
299         cache_file->f_pos = clone_file->f_pos;
300         cache_file->f_mode = clone_file->f_mode;
301         cache_file->f_flags = clone_file->f_flags;
302         cache_file->f_count  = clone_file->f_count;
303         cache_file->f_owner  = clone_file->f_owner;
304         cache_file->f_op = cache_inode->i_fop;
305         cache_file->f_dentry = cache_dentry;
306         cache_file->f_dentry->d_inode = cache_inode;
307         
308         EXIT;
309 }
310
311 /* update the clonefs file struct after IO in cache file */
312 static void clonefs_restore_snapfile(struct inode *cache_inode,
313                                    struct file *cache_file, 
314                                    struct inode *clone_inode,
315                                    struct file *clone_file)
316 {
317         ENTRY;
318  
319         cache_file->f_pos = clone_file->f_pos;
320         cache_inode->i_size = clone_inode->i_size;
321         
322         EXIT;
323 }
324
325 static int clonefs_readdir(struct file *file, void *dirent, 
326                            filldir_t filldir)
327 {
328         int result;
329         struct inode *cache_inode;
330         struct file open_file;
331         struct dentry open_dentry;
332         struct inode *inode = file->f_dentry->d_inode;
333
334         ENTRY;
335
336         if(!inode) {
337                 RETURN(-EINVAL);
338         }
339         cache_inode = clonefs_get_inode(inode);
340
341         if (!cache_inode) {
342                 make_bad_inode(inode);
343                 RETURN(-ENOMEM);
344         }
345
346         CDEBUG(D_INODE,"clone ino %ld\n",cache_inode->i_ino);
347
348         clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
349                               &open_dentry);
350         /* potemkin case: we are handed a directory inode */
351         result = -ENOENT;
352         if (open_file.f_op->readdir) {
353                 down(&cache_inode->i_sem);
354                 result = open_file.f_op->readdir(&open_file, dirent, filldir);
355                 up(&cache_inode->i_sem);
356         }
357         clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
358         iput(cache_inode);
359         RETURN(result);
360 }
361
362 struct file_operations clonefs_dir_file_ops = {
363         readdir:        clonefs_readdir,        /* readdir */
364 };
365
366 struct inode_operations clonefs_dir_inode_ops = {
367         lookup:         clonefs_lookup,   /* lookup */
368 };
369
370
371 /* ***************** end of clonefs dir ops *******************  */ 
372 /* ***************** begin clonefs file ops *******************  */ 
373
374 static int clonefs_readpage(struct file *file, struct page *page)
375 {
376         int result = 0;
377         struct inode *cache_inode;
378         struct file open_file;
379         struct dentry open_dentry;
380         struct inode *inode;
381
382         ENTRY;
383
384         inode = file->f_dentry->d_inode;
385         cache_inode = clonefs_get_inode(file->f_dentry->d_inode); 
386         if (!cache_inode) {
387                 make_bad_inode(file->f_dentry->d_inode);
388                 RETURN(-ENOMEM);
389         }
390
391         clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
392                               &open_dentry);
393         /* tell currentfs_readpage the primary inode number */
394         open_dentry.d_fsdata = (void*)inode->i_ino;
395         page->mapping->host = cache_inode;
396         /* potemkin case: we are handed a directory inode */
397         down(&cache_inode->i_sem);
398         /* XXX - readpage NULL on directories... */
399         result = cache_inode->i_mapping->a_ops->readpage(&open_file, page);
400
401         up(&cache_inode->i_sem);
402         page->mapping->host = inode;
403         clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
404         iput(cache_inode);
405         RETURN(result);
406 }
407
408 struct file_operations clonefs_file_file_ops = {
409         read:   generic_file_read,      /* read -- bad */
410         mmap:   generic_file_mmap,      /* mmap */
411 };
412
413 struct address_space_operations clonefs_file_address_ops = {
414         readpage:       clonefs_readpage
415 };
416
417
418 /* ***************** end of clonefs file ops *******************  */ 
419 /* ***************** begin clonefs symlink ops *******************  */ 
420
421 static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
422 {
423         int res;
424         struct inode * cache_inode;
425         struct inode * old_inode;
426
427         ENTRY;
428
429         cache_inode = clonefs_get_inode(dentry->d_inode); 
430
431         res = -ENOENT;
432
433         if ( ! cache_inode ) {
434                 CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
435                 RETURN(res);    
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                 res = 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(res);
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    res;
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(-ENOENT);        
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                 res = 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(res);
494 }
495
496 struct inode_operations clonefs_symlink_inode_ops =
497 {
498         /*FIXME later getxattr, listxattr, 
499          * other method need to be replaced too 
500          * */  
501         readlink:       clonefs_readlink,   /* readlink */              
502         follow_link:    clonefs_follow_link,/* follow_link */             
503 };
504
505