4 * A snap shot file system.
11 #define __NO_VERSION__
12 #include <linux/module.h>
13 #include <asm/uaccess.h>
14 #include <linux/sched.h>
15 #include <linux/stat.h>
16 #include <linux/string.h>
17 #include <linux/locks.h>
18 #include <linux/quotaops.h>
19 #include <linux/list.h>
20 #include <linux/file.h>
21 #include <asm/bitops.h>
22 #include <asm/byteorder.h>
24 #ifdef CONFIG_SNAPFS_EXT2
25 #include <linux/ext2_fs.h>
27 #ifdef CONFIG_SNAPFS_EXT3
28 #include <linux/ext3_fs.h>
31 #include <linux/filter.h>
32 #include <linux/snapfs.h>
33 #include <linux/snapsupport.h>
36 extern int currentfs_remount(struct super_block * sb, int *flags, char *data);
38 /* XXX PJB: this is exactly what we need to put things under
39 filters - we don't want the ext2 methods hardcoded, we want them
40 in the filter (in read_super) and then call those methods.
41 See how InterMezzo gets the journal operations .
44 extern void currentfs_dotsnap_read_inode(struct snap_cache *, struct inode *);
46 /* Superblock operations. */
47 static void currentfs_read_inode(struct inode *inode)
49 struct snap_cache *cache;
58 CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
60 cache = snap_find_cache(inode->i_dev);
62 printk("currentfs_read_inode: cannot find cache\n");
63 make_bad_inode(inode);
68 if ( inode->i_ino & 0xF0000000 ) {
69 CDEBUG(D_INODE, "\n");
70 currentfs_dotsnap_read_inode(cache, inode);
75 if( filter_c2csops(cache->cache_filter) )
76 filter_c2csops(cache->cache_filter)->read_inode(inode);
78 /* XXX now set the correct snap_{file,dir,sym}_iops */
79 if ( S_ISDIR(inode->i_mode) )
80 inode->i_op = filter_c2udiops(cache->cache_filter);
81 else if ( S_ISREG(inode->i_mode) ) {
82 if ( !filter_c2cfiops(cache->cache_filter) ) {
83 filter_setup_file_ops(cache->cache_filter,
84 inode->i_op, ¤tfs_file_iops);
86 inode->i_op = filter_c2ufiops(cache->cache_filter);
87 printk("inode %lu, i_op at %p\n", inode->i_ino, inode->i_op);
89 else if ( S_ISLNK(inode->i_mode) ) {
90 if ( !filter_c2csiops(cache->cache_filter) ) {
91 filter_setup_symlink_ops(cache->cache_filter,
92 inode->i_op, ¤tfs_sym_iops);
94 inode->i_op = filter_c2usiops(cache->cache_filter);
95 printk("inode %lu, i_op at %p\n", inode->i_ino, inode->i_op);
103 static int currentfs_notify_change(struct dentry *dentry, struct iattr *iattr)
105 struct snap_cache *cache;
107 struct super_operations *sops;
111 if (currentfs_is_under_dotsnap(dentry)) {
116 cache = snap_find_cache(dentry->d_inode->i_dev);
122 /* XXX better alloc a new dentry */
124 if ( snap_needs_cow(dentry->d_inode) != -1 ) {
125 printk("notify_change:snap_needs_cow for ino %lu \n",
126 dentry->d_inode->i_ino);
127 snap_do_cow(dentry->d_inode,
128 dentry->d_parent->d_inode->i_ino, 0);
131 sops = filter_c2csops(cache->cache_filter);
133 !sops->notify_change) {
137 rc = sops->notify_change(dentry, iattr);
144 static void currentfs_put_super(struct super_block *sb)
147 struct snap_cache *cache;
150 CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
151 (ulong) sb, (ulong) sb->u.generic_sbp);
152 cache = snap_find_cache(sb->s_dev);
157 /* handle COMPAT_FEATUREs */
158 #ifdef CONFIG_SNAPFS_EXT2
159 else if( cache->cache_type == FILTER_FS_EXT2 ){
160 if( !EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_SNAPFS) ){
161 sb->u.ext2_sb.s_feature_compat &=
162 ~EXT2_FEATURE_COMPAT_BLOCKCOW;
163 sb->u.ext2_sb.s_es->s_feature_compat &=
164 cpu_to_le32(~EXT2_FEATURE_COMPAT_BLOCKCOW);
168 #ifdef CONFIG_SNAPFS_EXT3
169 else if( cache->cache_type == FILTER_FS_EXT3 ){
170 if( !EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_SNAPFS) ){
171 sb->u.ext3_sb.s_es->s_feature_compat &=
172 cpu_to_le32(~EXT3_FEATURE_COMPAT_BLOCKCOW);
177 * If there is a saved 'put_super' function for the underlying
180 if (cache->cache_filter->o_caops.cache_sops->put_super) {
181 cache->cache_filter->o_caops.cache_sops->put_super(sb);
184 if (!list_empty(&cache->cache_clone_list)) {
185 printk("Warning: snap_put_super: clones exist!\n");
188 list_del(&cache->cache_chain);
189 snap_free_cache(cache);
191 CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
192 (ulong) sb, (ulong) sb->u.generic_sbp);
194 CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n",
195 snap_kmemory, snap_vmemory);
201 struct super_operations currentfs_super_ops = {
202 currentfs_read_inode,
203 NULL, /* write inode */
204 NULL, /* put inode */
205 NULL, /* delete inode */
206 currentfs_notify_change,
208 NULL, /* write super */