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;
242 if (cache_iops->setattr && filter_iops->setattr)
243 u_iops->setattr = filter_iops->setattr;
244 if (cache_iops->setxattr && filter_iops->setxattr)
245 u_iops->setxattr = filter_iops->setxattr;
246 if (cache_iops->removexattr && filter_iops->removexattr)
247 u_iops->removexattr = filter_iops->removexattr;
253 struct file_operations *cache_fops = inode->i_fop;
255 if(cache_fops->readdir && filter_fops->readdir)
256 u_fops->readdir = filter_fops->readdir;
261 void filter_setup_file_ops(struct filter_fs *cache,
263 struct inode_operations *filter_iops,
264 struct file_operations *filter_fops,
265 struct address_space_operations *filter_aops)
267 struct inode_operations *u_iops;
268 struct file_operations *u_fops;
269 struct address_space_operations *u_aops;
272 if (cache->o_flags & FILTER_DID_FILE_OPS || !inode ) {
277 cache->o_flags |= FILTER_DID_FILE_OPS;
279 /* steal the old ops */
280 cache->o_caops.cache_file_iops = inode->i_op;
281 cache->o_caops.cache_file_fops = inode->i_fop;
284 u_iops = filter_c2ufiops(cache);
285 u_fops = filter_c2uffops(cache);
286 u_aops = filter_c2ufaops(cache);
288 /* setup our dir iops: copy and modify */
289 memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
290 memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
292 if (inode->i_mapping && inode->i_mapping->a_ops) {
293 cache->o_caops.cache_file_aops = inode->i_mapping->a_ops;
294 memcpy(u_aops, inode->i_mapping->a_ops,
295 sizeof(struct address_space_operations));
298 if (filter_iops->revalidate)
299 u_iops->revalidate = filter_iops->revalidate;
300 if (filter_iops->removexattr)
301 u_iops->removexattr = filter_iops->removexattr;
302 if (filter_iops->setxattr)
303 u_iops->setxattr = filter_iops->setxattr;
304 if (filter_iops->setattr)
305 u_iops->setattr = filter_iops->setattr;
308 if (filter_fops->read)
309 u_fops->read = filter_fops->read;
310 if (filter_fops->write)
311 u_fops->write = filter_fops->write;
314 if (filter_aops->readpage)
315 u_aops->readpage = filter_aops->readpage;
320 void filter_setup_symlink_ops(struct filter_fs *cache,
322 struct inode_operations *filter_iops,
323 struct file_operations *filter_fops)
325 struct inode_operations *u_iops;
326 struct file_operations *u_fops;
330 if (cache->o_flags & FILTER_DID_SYMLINK_OPS || !inode ) {
334 cache->o_flags |= FILTER_DID_SYMLINK_OPS;
336 /* steal the old ops */
337 cache->o_caops.cache_sym_iops = inode->i_op;
338 cache->o_caops.cache_sym_fops = inode->i_fop;
341 u_iops = filter_c2usiops(cache);
342 u_fops = filter_c2usfops(cache);
344 /* setup our dir iops: copy and modify */
345 memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
346 memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
348 struct inode_operations *cache_iops = inode->i_op;
349 if (cache_iops->readlink && filter_iops->readlink)
350 u_iops->readlink = filter_iops->readlink;
351 if (cache_iops->follow_link && filter_iops->follow_link)
352 u_iops->follow_link = filter_iops->follow_link;
353 if (cache_iops->getxattr && filter_iops->getxattr)
354 u_iops->getxattr = filter_iops->getxattr;
355 if (cache_iops->listxattr && filter_iops->listxattr)
356 u_iops->listxattr = filter_iops->listxattr;
362 void filter_setup_dentry_ops(struct filter_fs *cache,
363 struct dentry_operations *cache_dop,
364 struct dentry_operations *filter_dop)
366 if ( cache->o_flags & FILTER_DID_DENTRY_OPS ) {
370 cache->o_flags |= FILTER_DID_DENTRY_OPS;
372 cache->o_caops.cache_dentry_ops = cache_dop;
373 memcpy(&cache->o_fops.filter_dentry_ops,
374 filter_dop, sizeof(*filter_dop));
376 if (cache_dop && cache_dop != filter_dop && cache_dop->d_revalidate){
377 CWARN("filter overriding revalidation!\n");
382 /* snapfs : for snapshot operations */
383 void filter_setup_snapshot_ops (struct filter_fs *cache,
384 struct snapshot_operations *cache_snapops)
388 if ( cache->o_flags & FILTER_DID_SNAPSHOT_OPS ) {
392 cache->o_flags |= FILTER_DID_SNAPSHOT_OPS;
394 cache->o_snapops = cache_snapops;
399 void filter_setup_journal_ops (struct filter_fs *cache,
400 struct journal_ops *cache_journal_ops)
404 if( cache->o_flags & FILTER_DID_JOURNAL_OPS ){
408 cache->o_flags |= FILTER_DID_JOURNAL_OPS;
410 cache->o_trops = cache_journal_ops;