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 DEBUG_SUBSYSTEM S_SNAP
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"
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
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;
44 /* support routines for following redirectors */
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.
50 We return an underlying (likely disk) fs inode. This involved
51 handling any redirector inodes found along the way.
53 This function is used by all clone fs interface functions to get an
57 struct inode *clonefs_get_inode(struct inode *inode)
59 struct snap_clone_info *clone_sb;
60 struct inode *cache_inode, *redirected_inode;
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;
67 /* basic invariant: clone and current ino's are equal */
68 cache_inode = iget(clone_sb->clone_cache->cache_sb, inode->i_ino);
70 redirected_inode = snap_redirect(cache_inode, inode->i_sb);
72 CDEBUG(D_SNAP, "redirected_inode: %lx, cache_inode %lx\n",
73 (unsigned long) redirected_inode, (unsigned long) cache_inode);
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));
81 return redirected_inode;
85 /* super operations */
86 static void clonefs_read_inode(struct inode *inode)
88 struct inode *cache_inode;
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));
96 /* redirecting inode in the cache */
97 cache_inode = clonefs_get_inode(inode);
99 make_bad_inode(inode);
102 /* copy attrs of that inode to our clone inode */
103 snapfs_cpy_attrs(inode, cache_inode);
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;
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));
122 init_special_inode(inode, inode->i_mode, inode->i_rdev);
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));
135 static void clonefs_put_super(struct super_block *sb)
137 struct snap_clone_info *clone_sb;
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);
146 put_snap_current_mnt(clone_sb->clone_cache->cache_sb);
151 static int clonefs_statfs(struct super_block *sb, struct statfs *buf)
153 struct snap_clone_info *clone_sb;
154 struct snap_cache *cache;
157 clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
159 cache = clone_sb->clone_cache;
161 CERROR("clone_statfs: no cache\n");
165 return cache->cache_filter->o_caops.cache_sops->statfs
166 (cache->cache_sb, buf);
169 struct super_operations clone_super_ops =
171 read_inode: clonefs_read_inode, /* read_inode */
172 put_super: clonefs_put_super, /* put_super */
173 statfs: clonefs_statfs, /* statfs */
177 /* ***************** end of clonefs super ops ******************* */
178 /* ***************** begin clonefs dir ops ******************* */
180 static void d_unalloc(struct dentry *dentry)
183 list_del(&dentry->d_hash);
184 INIT_LIST_HEAD(&dentry->d_hash);
185 dput(dentry); /* this will free the dentry memory */
188 static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
190 atomic_set(&dentry->d_count, 1);
191 dentry->d_vfs_flags = 0;
193 dentry->d_inode = inode;
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);
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 = NULL;
210 struct dentry *cache_dentry = NULL;
211 struct inode *cache_inode;
212 struct dentry *result;
215 struct snap_clone_info *clone_sb;
219 cache_dir = clonefs_get_inode(dir);
221 RETURN(ERR_PTR(-ENOENT));
222 /*FIXME later, we make parent dentry here
223 *there may some problems in lookup
225 prepare_parent_dentry(&tmp, cache_dir);
226 cache_dentry = d_alloc(&tmp, &dentry->d_name);
230 RETURN(ERR_PTR(-ENOENT));
233 /* Lock cache directory inode. */
234 down(&cache_dir->i_sem);
236 * Call underlying fs lookup function to set the 'd_inode' pointer
237 * to the corresponding directory inode.
239 * Note: If the lookup function does not return NULL, return
240 * from 'clone_lookup' with an error.
242 result = cache_dir->i_op->lookup(cache_dir, cache_dentry);
245 up(&cache_dir->i_sem);
247 dentry->d_inode = NULL;
248 RETURN(ERR_PTR(-ENOENT));
250 /* Unlock cache directory inode. */
251 up(&cache_dir->i_sem);
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;
258 cache_inode = cache_dentry->d_inode;
259 if ( cache_inode == NULL ) {
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
266 inode = iget(dir->i_sb, cache_inode->i_ino);
269 /* dput(cache_dentry) will not put the dentry away
270 * immediately, unless we first arrange that its hash list is
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));
280 d_unalloc(cache_dentry);
284 * Add 'inode' to the directory entry 'dentry'.
286 d_add(dentry, inode);
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)
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;
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)
321 cache_file->f_pos = clone_file->f_pos;
322 cache_inode->i_size = clone_inode->i_size;
327 static int clonefs_readdir(struct file *file, void *dirent,
331 struct inode *cache_inode;
332 struct file open_file;
333 struct dentry open_dentry;
334 struct inode *inode = file->f_dentry->d_inode;
341 cache_inode = clonefs_get_inode(inode);
344 make_bad_inode(inode);
348 CDEBUG(D_INODE,"clone ino %ld\n",cache_inode->i_ino);
350 clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
352 /* potemkin case: we are handed a directory inode */
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);
359 clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
364 struct file_operations clonefs_dir_file_ops = {
365 readdir: clonefs_readdir, /* readdir */
368 struct inode_operations clonefs_dir_inode_ops = {
369 lookup: clonefs_lookup, /* lookup */
373 /* ***************** end of clonefs dir ops ******************* */
374 /* ***************** begin clonefs file ops ******************* */
376 static int clonefs_readpage(struct file *file, struct page *page)
379 struct inode *cache_inode;
380 struct file open_file;
381 struct dentry open_dentry;
386 inode = file->f_dentry->d_inode;
387 cache_inode = clonefs_get_inode(file->f_dentry->d_inode);
389 make_bad_inode(file->f_dentry->d_inode);
393 clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
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);
403 up(&cache_inode->i_sem);
404 page->mapping->host = inode;
405 clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
410 struct file_operations clonefs_file_file_ops = {
411 read: generic_file_read, /* read -- bad */
412 mmap: generic_file_mmap, /* mmap */
415 struct address_space_operations clonefs_file_address_ops = {
416 readpage: clonefs_readpage
420 /* ***************** end of clonefs file ops ******************* */
421 /* ***************** begin clonefs symlink ops ******************* */
423 static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
426 struct inode * cache_inode;
427 struct inode * old_inode;
431 cache_inode = clonefs_get_inode(dentry->d_inode);
435 if ( ! cache_inode ) {
436 CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
440 /* XXX: shall we allocate a new dentry ?
441 The following is safe for ext3, etc. because ext2_readlink only
442 use the inode info */
444 /* save the old dentry inode */
445 old_inode = dentry->d_inode;
446 /* set dentry inode to cache inode */
447 dentry->d_inode = cache_inode;
449 if ( cache_inode->i_op->readlink ) {
450 res = cache_inode->i_op->readlink(dentry, buf, len);
452 CDEBUG(D_INODE,"NO readlink for ino %lu\n", cache_inode->i_ino);
455 /* restore the old inode */
456 dentry->d_inode = old_inode;
463 static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
465 struct inode * cache_inode;
466 struct inode * old_inode;
471 cache_inode = clonefs_get_inode(dentry->d_inode);
472 if ( ! cache_inode ) {
473 CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
477 /* XXX: shall we allocate a new dentry ?
478 The following is safe for ext2, etc. because ext2_follow_link
479 only use the inode info */
481 /* save the old dentry inode */
482 old_inode = dentry->d_inode;
483 /* set dentry inode to cache inode */
484 dentry->d_inode = cache_inode;
486 if ( cache_inode->i_op->follow_link ) {
487 res = cache_inode->i_op->follow_link(dentry, nd);
490 /* restore the old inode */
491 dentry->d_inode = old_inode;
498 struct inode_operations clonefs_symlink_inode_ops =
500 /*FIXME later getxattr, listxattr,
501 * other method need to be replaced too
503 readlink: clonefs_readlink, /* readlink */
504 follow_link: clonefs_follow_link,/* follow_link */