4 * Copyright (C) 2000 Stelias Computing, Inc.
5 * Copyright (C) 2000 Red Hat, Inc.
6 * Copyright (C) 2000 Mountain View Data, Inc.
13 #include <asm/bitops.h>
14 #include <asm/uaccess.h>
15 #include <asm/system.h>
17 #include <linux/errno.h>
19 #include <linux/ext2_fs.h>
20 #include <linux/malloc.h>
21 #include <linux/vmalloc.h>
22 #include <linux/sched.h>
23 #include <linux/stat.h>
24 #include <linux/string.h>
25 #include <linux/locks.h>
26 #include <linux/blkdev.h>
27 #include <linux/init.h>
28 #define __NO_VERSION__
29 #include <linux/module.h>
31 #include <linux/filter.h>
33 int filter_print_entry = 1;
34 int filter_debug = 0xfffffff;
36 * The function in this file are responsible for setting up the
37 * correct methods layered file systems like InterMezzo and SnapFS
41 static struct filter_fs filter_oppar[FILTER_FS_TYPES];
43 /* get to the upper methods (intermezzo, snapfs) */
44 inline struct super_operations *filter_c2usops(struct filter_fs *cache)
46 return &cache->o_fops.filter_sops;
49 inline struct inode_operations *filter_c2udiops(struct filter_fs *cache)
51 return &cache->o_fops.filter_dir_iops;
54 inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache)
56 return &cache->o_fops.filter_file_iops;
59 inline struct inode_operations *filter_c2usiops(struct filter_fs *cache)
61 return &cache->o_fops.filter_sym_iops;
64 inline struct file_operations *filter_c2udfops(struct filter_fs *cache)
66 return &cache->o_fops.filter_dir_fops;
69 inline struct file_operations *filter_c2uffops(struct filter_fs *cache)
71 return &cache->o_fops.filter_file_fops;
74 inline struct file_operations *filter_c2usfops(struct filter_fs *cache)
76 return &cache->o_fops.filter_sym_fops;
79 inline struct dentry_operations *filter_c2udops(struct filter_fs *cache)
81 return &cache->o_fops.filter_dentry_ops;
84 /* get to the cache (lower) methods */
85 inline struct super_operations *filter_c2csops(struct filter_fs *cache)
87 return cache->o_caops.cache_sops;
90 inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache)
92 return cache->o_caops.cache_dir_iops;
95 inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache)
97 return cache->o_caops.cache_file_iops;
100 inline struct inode_operations *filter_c2csiops(struct filter_fs *cache)
102 return cache->o_caops.cache_sym_iops;
105 inline struct file_operations *filter_c2cdfops(struct filter_fs *cache)
107 return cache->o_caops.cache_dir_fops;
110 inline struct file_operations *filter_c2cffops(struct filter_fs *cache)
112 return cache->o_caops.cache_file_fops;
115 inline struct file_operations *filter_c2csfops(struct filter_fs *cache)
117 return cache->o_caops.cache_sym_fops;
120 inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache)
122 return cache->o_caops.cache_dentry_ops;
124 /* snapfs: for snapshot operations */
125 inline struct snapshot_operations *filter_c2csnapops(struct filter_fs *cache)
127 return cache->o_snapops;
130 /* find the cache for this FS */
131 struct filter_fs *filter_get_filter_fs(const char *cache_type)
133 struct filter_fs *ops = NULL;
136 if ( strlen(cache_type) == strlen("ext2") &&
137 memcmp(cache_type, "ext2", strlen("ext2")) == 0 ) {
138 ops = &filter_oppar[FILTER_FS_EXT2];
139 FDEBUG(D_SUPER, "ops at %p\n", ops);
142 if ( strlen(cache_type) == strlen("ext3") &&
143 memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) {
144 ops = &filter_oppar[FILTER_FS_EXT3];
145 FDEBUG(D_SUPER, "ops at %p\n", ops);
147 if ( strlen(cache_type) == strlen("reiser") &&
148 memcmp(cache_type, "reiser", strlen("reiser")) == 0 ) {
149 ops = &filter_oppar[FILTER_FS_REISER];
150 FDEBUG(D_SUPER, "ops at %p\n", ops);
154 printk("prepare to die: unrecognized cache type for Filter\n");
162 * Frobnicate the InterMezzo/SnapFS operations
163 * this establishes the link between the InterMezzo/SnapFS file system
164 * and the underlying file system used for the cache.
167 void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_sops, struct super_operations *filter_sops)
169 /* Get ptr to the shared struct snapfs_ops structure. */
170 struct filter_ops *uops = &cache->o_fops;
171 /* Get ptr to the shared struct cache_ops structure. */
172 struct cache_ops *caops = &cache->o_caops;
176 if ( cache->o_flags & FILTER_DID_SUPER_OPS ) {
180 cache->o_flags |= FILTER_DID_SUPER_OPS;
182 /* Set the cache superblock operations to point to the
183 superblock operations of the underlying file system. */
184 caops->cache_sops = cache_sops;
187 * Copy the cache (real fs) superblock ops to the "filter"
188 * superblock ops as defaults. Some will be changed below
190 memcpy(&uops->filter_sops, cache_sops, sizeof(*cache_sops));
192 /* now overwrite with filtering ops */
193 if (cache_sops->put_super && uops->filter_sops.put_super) {
194 uops->filter_sops.put_super = filter_sops->put_super;
196 if (cache_sops->read_inode && uops->filter_sops.read_inode) {
197 uops->filter_sops.read_inode = filter_sops->read_inode;
198 FDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %p\n",
199 cache, cache, uops->filter_sops.read_inode);
201 if (cache_sops->notify_change && uops->filter_sops.notify_change)
202 uops->filter_sops.notify_change = filter_sops->notify_change;
203 if (cache_sops->remount_fs && uops->filter_sops.remount_fs)
204 uops->filter_sops.remount_fs = filter_sops->remount_fs;
209 void filter_setup_dir_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops)
211 struct inode_operations *u_iops;
212 struct file_operations *u_fops, *c_fops, *f_fops;
215 if ( cache->o_flags & FILTER_DID_DIR_OPS ) {
219 FDEBUG(D_SUPER, "\n");
220 cache->o_flags |= FILTER_DID_DIR_OPS;
222 /* steal the old ops */
223 cache->o_caops.cache_dir_iops = cache_iops;
224 cache->o_caops.cache_dir_fops =
225 cache_iops->default_file_ops;
227 FDEBUG(D_SUPER, "\n");
229 u_iops = &cache->o_fops.filter_dir_iops;
231 /* setup our dir iops: copy and modify */
232 memcpy(u_iops, cache_iops, sizeof(*cache_iops));
233 FDEBUG(D_SUPER, "\n");
235 /* methods that filter if cache filesystem has these ops */
236 if ( cache_iops->lookup && filter_iops->lookup ) {
237 FDEBUG(D_SUPER, "\n");
238 u_iops->lookup = filter_iops->lookup;
239 FDEBUG(D_SUPER, "lookup at %p\n", &filter_iops->lookup);
241 if (cache_iops->create && filter_iops->create)
242 u_iops->create = filter_iops->create;
243 FDEBUG(D_SUPER, "\n");
244 if (cache_iops->link && filter_iops->link)
245 u_iops->link = filter_iops->link;
246 FDEBUG(D_SUPER, "\n");
247 if (cache_iops->unlink && filter_iops->unlink)
248 u_iops->unlink = filter_iops->unlink;
249 FDEBUG(D_SUPER, "\n");
250 if (cache_iops->mkdir && filter_iops->mkdir)
251 u_iops->mkdir = filter_iops->mkdir;
252 FDEBUG(D_SUPER, "\n");
253 if (cache_iops->rmdir && filter_iops->rmdir)
254 u_iops->rmdir = filter_iops->rmdir;
255 FDEBUG(D_SUPER, "\n");
256 if (cache_iops->symlink && filter_iops->symlink)
257 u_iops->symlink = filter_iops->symlink;
258 FDEBUG(D_SUPER, "\n");
259 if (cache_iops->rename && filter_iops->rename)
260 u_iops->rename = filter_iops->rename;
261 FDEBUG(D_SUPER, "\n");
262 if (cache_iops->mknod && filter_iops->mknod)
263 u_iops->mknod = filter_iops->mknod;
264 FDEBUG(D_SUPER, "\n");
265 if (cache_iops->permission && filter_iops->permission)
266 u_iops->permission = filter_iops->permission;
269 FDEBUG(D_SUPER, "\n");
270 u_fops = &cache->o_fops.filter_dir_fops;
271 c_fops = cache_iops->default_file_ops;
272 f_fops = filter_iops->default_file_ops;
274 memcpy(u_fops, c_fops, sizeof(*c_fops));
276 if( c_fops->readdir && f_fops->readdir )
277 u_fops->readdir = f_fops->readdir;
280 FDEBUG(D_SUPER, "\n");
281 filter_c2udiops(cache)->default_file_ops = filter_c2udfops(cache);
282 FDEBUG(D_SUPER, "\n");
284 /* unconditional filtering operations */
285 if ( filter_iops->default_file_ops &&
286 filter_iops->default_file_ops->open )
287 filter_c2udfops(cache)->open =
288 filter_iops->default_file_ops->open;
294 void filter_setup_file_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops)
296 struct inode_operations *u_iops;
299 if ( cache->o_flags & FILTER_DID_FILE_OPS ) {
303 cache->o_flags |= FILTER_DID_FILE_OPS;
305 /* steal the old ops */
306 cache->o_caops.cache_file_iops = cache_iops;
307 cache->o_caops.cache_file_fops =
308 cache_iops->default_file_ops;
311 u_iops = filter_c2ufiops(cache);
313 /* setup our dir iops: copy and modify */
314 memcpy(u_iops, cache_iops, sizeof(*cache_iops));
317 memcpy(filter_c2uffops(cache), cache_iops->default_file_ops,
318 sizeof(*cache_iops->default_file_ops));
320 filter_c2ufiops(cache)->default_file_ops = filter_c2uffops(cache);
322 /* unconditional filtering operations */
323 if (filter_iops->default_file_ops &&
324 filter_iops->default_file_ops->open )
325 filter_c2uffops(cache)->open =
326 filter_iops->default_file_ops->open;
327 if (filter_iops->default_file_ops &&
328 filter_iops->default_file_ops->release )
329 filter_c2uffops(cache)->release =
330 filter_iops->default_file_ops->release;
331 if (filter_iops->default_file_ops &&
332 filter_iops->default_file_ops->write )
333 filter_c2uffops(cache)->write =
334 filter_iops->default_file_ops->write;
336 /* set up readpage */
337 if (filter_iops->readpage)
338 filter_c2ufiops(cache)->readpage = filter_iops->readpage;
343 /* XXX in 2.3 there are "fast" and "slow" symlink ops for ext2 XXX */
344 void filter_setup_symlink_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops)
346 struct inode_operations *u_iops;
349 if ( cache->o_flags & FILTER_DID_SYMLINK_OPS ) {
353 cache->o_flags |= FILTER_DID_SYMLINK_OPS;
355 /* steal the old ops */
356 cache->o_caops.cache_sym_iops = cache_iops;
357 cache->o_caops.cache_sym_fops =
358 cache_iops->default_file_ops;
361 u_iops = filter_c2usiops(cache);
363 /* setup our dir iops: copy and modify */
364 memcpy(u_iops, cache_iops, sizeof(*cache_iops));
366 /* copy fops - careful for symlinks they might be NULL */
367 if ( cache_iops->default_file_ops ) {
368 memcpy(filter_c2usfops(cache), cache_iops->default_file_ops,
369 sizeof(*cache_iops->default_file_ops));
373 filter_c2usiops(cache)->default_file_ops = filter_c2usfops(cache);
375 if (cache_iops->readlink && filter_iops->readlink)
376 u_iops->readlink = filter_iops->readlink;
377 if (cache_iops->follow_link && filter_iops->follow_link)
378 u_iops->follow_link = filter_iops->follow_link;
383 void filter_setup_dentry_ops(struct filter_fs *cache,
384 struct dentry_operations *cache_dop,
385 struct dentry_operations *filter_dop)
387 if ( cache->o_flags & FILTER_DID_DENTRY_OPS ) {
391 cache->o_flags |= FILTER_DID_DENTRY_OPS;
393 cache->o_caops.cache_dentry_ops = cache_dop;
394 memcpy(&cache->o_fops.filter_dentry_ops,
395 filter_dop, sizeof(*filter_dop));
397 if (cache_dop && cache_dop != filter_dop && cache_dop->d_revalidate){
398 printk("WARNING: filter overriding revalidation!\n");
402 /* snapfs : for snapshot operations */
403 void filter_setup_snapshot_ops (struct filter_fs *cache,
404 struct snapshot_operations *cache_snapops)
408 if ( cache->o_flags & FILTER_DID_SNAPSHOT_OPS ) {
412 cache->o_flags |= FILTER_DID_SNAPSHOT_OPS;
414 cache->o_snapops = cache_snapops;
419 void filter_setup_journal_ops (struct filter_fs *cache,
420 struct journal_ops *cache_journal_ops)
424 if( cache->o_flags & FILTER_DID_JOURNAL_OPS ){
428 cache->o_flags |= FILTER_DID_JOURNAL_OPS;
430 cache->o_trops = cache_journal_ops;