4 #define DEBUG_SUBSYSTEM S_SNAP
6 #include <linux/module.h>
7 #include <linux/kernel.h>
8 #include <linux/string.h>
9 #include <linux/slab.h>
10 #include <linux/stat.h>
11 #include <linux/unistd.h>
12 #include <linux/jbd.h>
13 #include <linux/ext3_fs.h>
14 #include <linux/snap.h>
16 #include "snapfs_internal.h"
20 * The function in this file are responsible for setting up the
21 * correct methods layered file systems like InterMezzo and SnapFS
25 static struct filter_fs filter_oppar[FILTER_FS_TYPES];
27 /* get to the upper methods (intermezzo, snapfs) */
28 inline struct super_operations *filter_c2usops(struct filter_fs *cache)
30 return &cache->o_fops.filter_sops;
33 inline struct inode_operations *filter_c2udiops(struct filter_fs *cache)
35 return &cache->o_fops.filter_dir_iops;
38 inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache)
40 return &cache->o_fops.filter_file_iops;
43 inline struct inode_operations *filter_c2usiops(struct filter_fs *cache)
45 return &cache->o_fops.filter_sym_iops;
48 inline struct file_operations *filter_c2udfops(struct filter_fs *cache)
50 return &cache->o_fops.filter_dir_fops;
53 inline struct file_operations *filter_c2uffops(struct filter_fs *cache)
55 return &cache->o_fops.filter_file_fops;
58 inline struct address_space_operations *filter_c2ufaops(struct filter_fs *cache)
60 return &cache->o_fops.filter_file_aops;
63 inline struct file_operations *filter_c2usfops(struct filter_fs *cache)
65 return &cache->o_fops.filter_sym_fops;
68 inline struct dentry_operations *filter_c2udops(struct filter_fs *cache)
70 return &cache->o_fops.filter_dentry_ops;
73 /* get to the cache (lower) methods */
74 inline struct super_operations *filter_c2csops(struct filter_fs *cache)
76 return cache->o_caops.cache_sops;
79 inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache)
81 return cache->o_caops.cache_dir_iops;
84 inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache)
86 return cache->o_caops.cache_file_iops;
89 inline struct address_space_operations *filter_c2cfaops(struct filter_fs *cache)
91 return cache->o_caops.cache_file_aops;
94 inline struct inode_operations *filter_c2csiops(struct filter_fs *cache)
96 return cache->o_caops.cache_sym_iops;
99 inline struct file_operations *filter_c2cdfops(struct filter_fs *cache)
101 return cache->o_caops.cache_dir_fops;
104 inline struct file_operations *filter_c2cffops(struct filter_fs *cache)
106 return cache->o_caops.cache_file_fops;
109 inline struct file_operations *filter_c2csfops(struct filter_fs *cache)
111 return cache->o_caops.cache_sym_fops;
114 inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache)
116 return cache->o_caops.cache_dentry_ops;
118 /* snapfs: for snapshot operations */
119 inline struct snapshot_operations *filter_c2csnapops(struct filter_fs *cache)
121 return cache->o_snapops;
124 /* find the cache for this FS */
125 struct filter_fs *filter_get_filter_fs(const char *cache_type)
127 struct filter_fs *ops = NULL;
130 if ((strlen(cache_type) == strlen("ext3") &&
131 memcmp(cache_type, "ext3", strlen("ext3")) == 0)) {
132 ops = &filter_oppar[FILTER_FS_EXT3];
133 CDEBUG(D_SUPER, "ops at %p\n", ops);
134 } else if ( strlen(cache_type) == strlen("reiser") &&
135 memcmp(cache_type, "reiser", strlen("reiser")) == 0 ) {
136 ops = &filter_oppar[FILTER_FS_REISER];
137 CDEBUG(D_SUPER, "ops at %p\n", ops);
139 CERROR("prepare to die: unrecognized cache type for Filter\n");
146 * Frobnicate the InterMezzo/SnapFS operations
147 * this establishes the link between the InterMezzo/SnapFS file system
148 * and the underlying file system used for the cache.
151 void filter_setup_super_ops(struct filter_fs *cache,
152 struct super_operations *cache_sops,
153 struct super_operations *filter_sops)
155 /* Get ptr to the shared struct snapfs_ops structure. */
156 struct filter_ops *uops = &cache->o_fops;
157 /* Get ptr to the shared struct cache_ops structure. */
158 struct cache_ops *caops = &cache->o_caops;
162 if ( cache->o_flags & FILTER_DID_SUPER_OPS ) {
166 cache->o_flags |= FILTER_DID_SUPER_OPS;
168 /* Set the cache superblock operations to point to the
169 superblock operations of the underlying file system. */
170 caops->cache_sops = cache_sops;
172 * Copy the cache (real fs) superblock ops to the "filter"
173 * superblock ops as defaults. Some will be changed below
175 memcpy(&uops->filter_sops, cache_sops, sizeof(*cache_sops));
177 /* now overwrite with filtering ops */
178 if (cache_sops->put_super && uops->filter_sops.put_super) {
179 uops->filter_sops.put_super = filter_sops->put_super;
181 if (cache_sops->read_inode && uops->filter_sops.read_inode) {
182 uops->filter_sops.read_inode = filter_sops->read_inode;
183 CDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %p\n",
184 cache, cache, uops->filter_sops.read_inode);
186 uops->filter_sops.clear_inode = filter_sops->clear_inode;
191 void filter_setup_dir_ops(struct filter_fs *cache,
193 struct inode_operations *filter_iops,
194 struct file_operations *filter_fops)
196 struct inode_operations *u_iops;
197 struct file_operations *u_fops;
201 if (cache->o_flags & FILTER_DID_DIR_OPS) {
205 cache->o_flags |= FILTER_DID_DIR_OPS;
207 /* steal the old ops */
208 cache->o_caops.cache_dir_iops = inode->i_op;
209 cache->o_caops.cache_dir_fops = inode->i_fop;
211 u_iops = filter_c2udiops(cache);
212 u_fops = filter_c2udfops(cache);
214 /* setup our dir iops and fops: copy and modify */
215 memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
216 memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
218 /* methods that filter if cache filesystem has these ops */
220 struct inode_operations *cache_iops = inode->i_op;
222 if (cache_iops->lookup && filter_iops->lookup)
223 u_iops->lookup = filter_iops->lookup;
224 if (cache_iops->create && filter_iops->create)
225 u_iops->create = filter_iops->create;
226 if (cache_iops->link && filter_iops->link)
227 u_iops->link = filter_iops->link;
228 if (cache_iops->unlink && filter_iops->unlink)
229 u_iops->unlink = filter_iops->unlink;
230 if (cache_iops->mkdir && filter_iops->mkdir)
231 u_iops->mkdir = filter_iops->mkdir;
232 if (cache_iops->rmdir && filter_iops->rmdir)
233 u_iops->rmdir = filter_iops->rmdir;
234 if (cache_iops->symlink && filter_iops->symlink)
235 u_iops->symlink = filter_iops->symlink;
236 if (cache_iops->rename && filter_iops->rename)
237 u_iops->rename = filter_iops->rename;
238 if (cache_iops->mknod && filter_iops->mknod)
239 u_iops->mknod = filter_iops->mknod;
240 if (cache_iops->permission && filter_iops->permission)
241 u_iops->permission = filter_iops->permission;
246 struct file_operations *cache_fops = inode->i_fop;
248 if(cache_fops->readdir && filter_fops->readdir)
249 u_fops->readdir = filter_fops->readdir;
254 void filter_setup_file_ops(struct filter_fs *cache,
256 struct inode_operations *filter_iops,
257 struct file_operations *filter_fops,
258 struct address_space_operations *filter_aops)
260 struct inode_operations *u_iops;
261 struct file_operations *u_fops;
262 struct address_space_operations *u_aops;
265 if (cache->o_flags & FILTER_DID_FILE_OPS || !inode ) {
270 cache->o_flags |= FILTER_DID_FILE_OPS;
272 /* steal the old ops */
273 cache->o_caops.cache_file_iops = inode->i_op;
274 cache->o_caops.cache_file_fops = inode->i_fop;
277 u_iops = filter_c2ufiops(cache);
278 u_fops = filter_c2uffops(cache);
279 u_aops = filter_c2ufaops(cache);
281 /* setup our dir iops: copy and modify */
282 memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
283 memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
285 if (inode->i_mapping && inode->i_mapping->a_ops) {
286 cache->o_caops.cache_file_aops = inode->i_mapping->a_ops;
287 memcpy(u_aops, inode->i_mapping->a_ops,
288 sizeof(struct address_space_operations));
291 if (filter_iops->revalidate)
292 u_iops->revalidate = filter_iops->revalidate;
295 if (filter_fops->read)
296 u_fops->read = filter_fops->read;
297 if (filter_fops->write)
298 u_fops->write = filter_fops->write;
301 if (filter_aops->readpage)
302 u_aops->readpage = filter_aops->readpage;
307 void filter_setup_symlink_ops(struct filter_fs *cache,
309 struct inode_operations *filter_iops,
310 struct file_operations *filter_fops)
312 struct inode_operations *u_iops;
313 struct file_operations *u_fops;
317 if (cache->o_flags & FILTER_DID_SYMLINK_OPS || !inode ) {
321 cache->o_flags |= FILTER_DID_SYMLINK_OPS;
323 /* steal the old ops */
324 cache->o_caops.cache_sym_iops = inode->i_op;
325 cache->o_caops.cache_sym_fops = inode->i_fop;
328 u_iops = filter_c2usiops(cache);
329 u_fops = filter_c2usfops(cache);
331 /* setup our dir iops: copy and modify */
332 memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
333 memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
335 struct inode_operations *cache_iops = inode->i_op;
336 if (cache_iops->readlink && filter_iops->readlink)
337 u_iops->readlink = filter_iops->readlink;
338 if (cache_iops->follow_link && filter_iops->follow_link)
339 u_iops->follow_link = filter_iops->follow_link;
344 void filter_setup_dentry_ops(struct filter_fs *cache,
345 struct dentry_operations *cache_dop,
346 struct dentry_operations *filter_dop)
348 if ( cache->o_flags & FILTER_DID_DENTRY_OPS ) {
352 cache->o_flags |= FILTER_DID_DENTRY_OPS;
354 cache->o_caops.cache_dentry_ops = cache_dop;
355 memcpy(&cache->o_fops.filter_dentry_ops,
356 filter_dop, sizeof(*filter_dop));
358 if (cache_dop && cache_dop != filter_dop && cache_dop->d_revalidate){
359 CWARN("filter overriding revalidation!\n");
364 /* snapfs : for snapshot operations */
365 void filter_setup_snapshot_ops (struct filter_fs *cache,
366 struct snapshot_operations *cache_snapops)
370 if ( cache->o_flags & FILTER_DID_SNAPSHOT_OPS ) {
374 cache->o_flags |= FILTER_DID_SNAPSHOT_OPS;
376 cache->o_snapops = cache_snapops;
381 void filter_setup_journal_ops (struct filter_fs *cache,
382 struct journal_ops *cache_journal_ops)
386 if( cache->o_flags & FILTER_DID_JOURNAL_OPS ){
390 cache->o_flags |= FILTER_DID_JOURNAL_OPS;
392 cache->o_trops = cache_journal_ops;