2 * Super block/filesystem wide operations
4 * Copryright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and
5 * Michael Callahan <callahan@maths.ox.ac.uk>
7 * Rewritten for Linux 2.1. Peter Braam <braam@cs.cmu.edu>
8 * Copyright (C) Carnegie Mellon University
10 * Copyright (C) 2000, Mountain View Data, Inc, authors
11 * Peter Braam <braam@mountainviewdata.com>,
12 * Harrison Xing <harrisonx@mountainviewdata.com>
16 #define __NO_VERSION__
17 #include <linux/module.h>
18 #include <linux/kernel.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>
26 #include <asm/system.h>
27 #include <asm/uaccess.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>
39 #include <linux/filter.h>
40 #include <linux/snapfs.h>
41 #include <linux/snapsupport.h>
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
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;
56 /* support routines for following redirectors */
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.
62 We return an underlying (likely disk) fs inode. This involved
63 handling any redirector inodes found along the way.
65 This function is used by all clone fs interface functions to get an
69 struct inode *clonefs_get_inode(struct inode *inode)
71 struct snap_clone_info *clone_sb;
72 struct inode *cache_inode, *redirected_inode;
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;
79 /* basic invariant: clone and current ino's are equal */
80 cache_inode = iget(clone_sb->clone_cache->cache_sb, inode->i_ino);
82 redirected_inode = snap_redirect(cache_inode, inode->i_sb);
84 CDEBUG(D_SNAP, "redirected_inode: %lx, cache_inode %lx\n",
85 (ulong) redirected_inode, (ulong) cache_inode);
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);
93 return redirected_inode;
97 /* super operations */
98 static void clonefs_read_inode(struct inode *inode)
100 struct inode *cache_inode;
104 CDEBUG(D_SNAP, "inode: %lx, ino %ld, sb %lx, count %d\n",
105 (ulong) inode , inode->i_ino, (long) inode->i_sb,
108 /* redirecting inode in the cache */
109 cache_inode = clonefs_get_inode(inode);
111 make_bad_inode(inode);
115 /* copy attrs of that inode to our clone inode */
116 snapfs_cpy_attrs(inode, cache_inode);
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))
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);
141 static void clonefs_put_super(struct super_block *sb)
143 struct snap_clone_info *clone_sb;
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);
157 static int clonefs_statfs(struct super_block *sb, struct statfs *buf,
160 struct snap_clone_info *clone_sb;
161 struct snap_cache *cache;
164 clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
166 cache = clone_sb->clone_cache;
168 printk("clone_statfs: no cache\n");
173 return cache->cache_filter->o_caops.cache_sops->statfs
174 (cache->cache_sb, buf, bufsiz);
177 struct super_operations clone_super_ops =
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 */
191 /* ***************** end of clonefs super ops ******************* */
192 /* ***************** begin clonefs dir ops ******************* */
194 static void d_unalloc(struct dentry *dentry)
197 list_del(&dentry->d_hash);
198 INIT_LIST_HEAD(&dentry->d_hash);
199 dput(dentry); /* this will free the dentry memory */
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
207 struct dentry *clonefs_lookup(struct inode *dir, struct dentry *dentry)
209 struct inode *cache_dir;
210 struct dentry *cache_dentry;
211 struct inode *cache_inode;
212 struct dentry *result;
214 struct snap_clone_info *clone_sb;
218 cache_dir = clonefs_get_inode(dir);
220 cache_dentry = d_alloc(dentry->d_parent, &dentry->d_name);
224 return ERR_PTR(-ENOENT);
227 /* Lock cache directory inode. */
228 down(&cache_dir->i_sem);
230 * Call underlying fs lookup function to set the 'd_inode' pointer
231 * to the corresponding directory inode.
233 * Note: If the lookup function does not return NULL, return
234 * from 'clone_lookup' with an error.
236 result = cache_dir->i_op->lookup(cache_dir, cache_dentry);
239 up(&cache_dir->i_sem);
241 dentry->d_inode = NULL;
243 return ERR_PTR(-ENOENT);
245 /* Unlock cache directory inode. */
246 up(&cache_dir->i_sem);
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;
253 cache_inode = cache_dentry->d_inode;
254 if ( cache_inode == NULL ) {
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
261 inode = iget(dir->i_sb, cache_inode->i_ino);
264 /* dput(cache_dentry) will not put the dentry away
265 * immediately, unless we first arrange that its hash list is
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,
275 d_unalloc(cache_dentry);
279 * Add 'inode' to the directory entry 'dentry'.
281 d_add(dentry, inode);
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)
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;
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)
315 cache_file->f_pos = clone_file->f_pos;
316 cache_inode->i_size = clone_inode->i_size;
321 static int clonefs_readdir(struct file *file, void *dirent,
325 struct inode *cache_inode;
326 struct file open_file;
327 struct dentry open_dentry;
328 struct inode *inode=file->f_dentry->d_inode;
336 cache_inode = clonefs_get_inode(inode);
339 make_bad_inode(inode);
344 CDEBUG(D_INODE,"clone ino %ld\n",cache_inode->i_ino);
346 clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
348 /* potemkin case: we are handed a directory inode */
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);
355 clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
361 struct file_operations clonefs_dir_file_operations = {
363 NULL, /* read -- bad */
365 clonefs_readdir, /* readdir */
378 struct inode_operations clonefs_dir_inode_operations =
380 &clonefs_dir_file_operations,
382 clonefs_lookup, /* lookup */
391 NULL, /* follow_link */
393 NULL, /* writepage */
396 NULL, /* permission */
398 NULL, /* update page */
399 NULL, /* revalidate */
403 /* ***************** end of clonefs dir ops ******************* */
404 /* ***************** begin clonefs file ops ******************* */
406 int clonefs_readpage(struct file *file, struct page *page)
409 struct inode *cache_inode;
410 struct file open_file;
411 struct dentry open_dentry;
416 inode = file->f_dentry->d_inode;
417 cache_inode = clonefs_get_inode(file->f_dentry->d_inode);
419 make_bad_inode(file->f_dentry->d_inode);
424 clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
426 /* tell currentfs_readpage the primary inode number */
427 open_dentry.d_fsdata = (void*)inode->i_ino;
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");
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);
444 struct file_operations clonefs_file_file_operations = {
446 generic_file_read, /* read -- bad */
451 generic_file_mmap, /* mmap */
461 struct inode_operations clonefs_file_inode_operations =
463 &clonefs_file_file_operations,
474 NULL, /* follow_link */
475 clonefs_readpage, /* readpage */
476 NULL, /* writepage */
479 NULL, /* permission */
481 NULL, /* update page */
482 NULL, /* revalidate */
487 /* ***************** end of clonefs file ops ******************* */
488 /* ***************** begin clonefs symlink ops ******************* */
490 int clonefs_readlink(struct dentry *dentry, char *buf, int len)
493 struct inode * cache_inode;
494 struct inode * old_inode;
498 cache_inode = clonefs_get_inode(dentry->d_inode);
502 if ( ! cache_inode ) {
503 CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
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 */
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;
517 if ( cache_inode->i_op->readlink ) {
518 res = cache_inode->i_op->readlink(dentry, buf, len);
520 CDEBUG(D_INODE,"NO readlink for ino %lu\n", cache_inode->i_ino);
523 /* restore the old inode */
524 dentry->d_inode = old_inode;
532 struct dentry * clonefs_follow_link(struct dentry * dentry,
537 struct inode * cache_inode;
538 struct inode * old_inode;
541 res = ERR_PTR(-ENOENT);
543 cache_inode = clonefs_get_inode(dentry->d_inode);
544 if ( ! cache_inode ) {
545 CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
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 */
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;
559 if ( cache_inode->i_op->follow_link ) {
560 res = cache_inode->i_op->follow_link(dentry, base, follow);
563 /* restore the old inode */
564 dentry->d_inode = old_inode;
572 struct inode_operations clonefs_symlink_inode_operations =
574 NULL, /* no file operations */
584 clonefs_readlink, /* readlink */
585 clonefs_follow_link,/* follow_link */
587 NULL, /* writepage */
590 NULL, /* permission */
592 NULL, /* update page */
593 NULL, /* revalidate */