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