Example #1
0
void presto_set_ops(struct inode *inode, struct  filter_fs *filter)
{
	ENTRY; 
        if (!inode || is_bad_inode(inode))
                return;
	if (inode->i_gid == presto_excluded_gid ) { 
		EXIT;
                CDEBUG(D_INODE, "excluded methods for %ld at %p, %p\n",
                       inode->i_ino, inode->i_op, inode->i_fop);
		return; 
	}
        if (S_ISREG(inode->i_mode)) {
                if ( !filter_c2cfiops(filter) ) {
                       filter_setup_file_ops(filter, 
					     inode, &presto_file_iops,
					     &presto_file_fops);
                }
		inode->i_op = filter_c2ufiops(filter);
		inode->i_fop = filter_c2uffops(filter);
                CDEBUG(D_INODE, "set file methods for %ld to %p\n",
                       inode->i_ino, inode->i_op);
        } else if (S_ISDIR(inode->i_mode)) {
		inode->i_op = filter_c2udiops(filter);
		inode->i_fop = filter_c2udfops(filter);
                CDEBUG(D_INODE, "set dir methods for %ld to %p lookup %p\n",
                       inode->i_ino, inode->i_op, inode->i_op->lookup);
        } else if (S_ISLNK(inode->i_mode)) {
                if ( !filter_c2csiops(filter)) {
                        filter_setup_symlink_ops(filter, 
                                                 inode,
                                                 &presto_sym_iops, 
						 &presto_sym_fops);
                }
		inode->i_op = filter_c2usiops(filter);
		inode->i_fop = filter_c2usfops(filter);
                CDEBUG(D_INODE, "set link methods for %ld to %p\n",
                       inode->i_ino, inode->i_op);
        }
	EXIT;
}
Example #2
0
void filter_setup_dir_ops(struct filter_fs *cache, struct inode *inode, struct inode_operations *filter_iops, struct file_operations *filter_fops)
{
        struct inode_operations *cache_filter_iops;
        struct inode_operations *cache_iops = inode->i_op;
        struct file_operations *cache_fops = inode->i_fop;
        FENTRY;

        if ( cache->o_flags & FILTER_DID_DIR_OPS ) {
                FEXIT;
                return;
        }
        cache->o_flags |= FILTER_DID_DIR_OPS;

        /* former ops become cache_ops */
        cache->o_caops.cache_dir_iops = cache_iops;
        cache->o_caops.cache_dir_fops = cache_fops;
        FDEBUG(D_SUPER, "filter at %p, cache iops %p, iops %p\n",
               cache, cache_iops, filter_c2udiops(cache));

        /* setup our dir iops: copy and modify */
        memcpy(filter_c2udiops(cache), cache_iops, sizeof(*cache_iops));

        /* abbreviate */
        cache_filter_iops = filter_c2udiops(cache);

        /* methods that filter if cache filesystem has these ops */
        if (cache_iops->lookup && filter_iops->lookup)
                cache_filter_iops->lookup = filter_iops->lookup;
        if (cache_iops->create && filter_iops->create)
                cache_filter_iops->create = filter_iops->create;
        if (cache_iops->link && filter_iops->link)
                cache_filter_iops->link = filter_iops->link;
        if (cache_iops->unlink && filter_iops->unlink)
                cache_filter_iops->unlink = filter_iops->unlink;
        if (cache_iops->mkdir && filter_iops->mkdir)
                cache_filter_iops->mkdir = filter_iops->mkdir;
        if (cache_iops->rmdir && filter_iops->rmdir)
                cache_filter_iops->rmdir = filter_iops->rmdir;
        if (cache_iops->symlink && filter_iops->symlink)
                cache_filter_iops->symlink = filter_iops->symlink;
        if (cache_iops->rename && filter_iops->rename)
                cache_filter_iops->rename = filter_iops->rename;
        if (cache_iops->mknod && filter_iops->mknod)
                cache_filter_iops->mknod = filter_iops->mknod;
        if (cache_iops->permission && filter_iops->permission)
                cache_filter_iops->permission = filter_iops->permission;
        if (cache_iops->getattr)
                cache_filter_iops->getattr = filter_iops->getattr;
        /* Some filesystems do not use a setattr method of their own
           instead relying on inode_setattr/write_inode. We still need to
           journal these so we make setattr an unconditional operation. 
           XXX: we should probably check for write_inode. SHP
        */
        /*if (cache_iops->setattr)*/
                cache_filter_iops->setattr = filter_iops->setattr;
#ifdef CONFIG_FS_EXT_ATTR
	/* For now we assume that posix acls are handled through extended
	* attributes. If this is not the case, we must explicitly trap 
	* posix_set_acl. SHP
	*/
	if (cache_iops->set_ext_attr && filter_iops->set_ext_attr)
		cache_filter_iops->set_ext_attr = filter_iops->set_ext_attr;
#endif


        /* copy dir fops */
        memcpy(filter_c2udfops(cache), cache_fops, sizeof(*cache_fops));

        /* unconditional filtering operations */
        filter_c2udfops(cache)->ioctl = filter_fops->ioctl;

        FEXIT;
}
/* We always need to remove the presto options before passing 
   mount options to cache FS */
struct super_block * presto_read_super(struct super_block * sb,
                                       void * data, int silent)
{
        struct file_system_type *fstype;
        struct presto_cache *cache = NULL;
        char *cache_data = NULL;
        char *cache_data_end;
        char *cache_type = NULL;
        char *fileset = NULL;
        char *channel = NULL;
        int err; 
        unsigned int minor;

        ENTRY;

        /* reserve space for the cache's data */
        PRESTO_ALLOC(cache_data, PAGE_SIZE);
        if ( !cache_data ) {
                CERROR("presto_read_super: Cannot allocate data page.\n");
                EXIT;
                goto out_err;
        }

        /* read and validate options */
        cache_data_end = presto_options(sb, data, cache_data, &cache_type, 
                                        &fileset, &channel);

        /* was there anything for the cache filesystem in the data? */
        if (cache_data_end == cache_data) {
                PRESTO_FREE(cache_data, PAGE_SIZE);
                cache_data = NULL;
        } else {
                CDEBUG(D_SUPER, "cache_data at %p is: %s\n", cache_data,
                       cache_data);
        }

        /* set up the cache */
        cache = presto_cache_init();
        if ( !cache ) {
                CERROR("presto_read_super: failure allocating cache.\n");
                EXIT;
                goto out_err;
        }
        cache->cache_type = cache_type;

        /* link cache to channel */ 
        minor = presto_set_channel(cache, channel);
        if (minor < 0) { 
                EXIT;
                goto out_err;
        }

        CDEBUG(D_SUPER, "Presto: type=%s, fset=%s, dev= %d, flags %x\n",
               cache_type, fileset?fileset:"NULL", minor, cache->cache_flags);

        MOD_INC_USE_COUNT;

        /* get the filter for the cache */
        fstype = get_fs_type(cache_type);
        cache->cache_filter = filter_get_filter_fs((const char *)cache_type); 
        if ( !fstype || !cache->cache_filter) {
                CERROR("Presto: unrecognized fs type or cache type\n");
                MOD_DEC_USE_COUNT;
                EXIT;
                goto out_err;
        }

        /* can we in fact mount the cache */ 
        if ((fstype->fs_flags & FS_REQUIRES_DEV) && !sb->s_bdev) {
                CERROR("filesystem \"%s\" requires a valid block device\n",
                                cache_type);
                MOD_DEC_USE_COUNT;
                EXIT;
                goto out_err;
        }

        sb = fstype->read_super(sb, cache_data, silent);

        /* this might have been freed above */
        if (cache_data) {
                PRESTO_FREE(cache_data, PAGE_SIZE);
                cache_data = NULL;
        }

        if ( !sb ) {
                CERROR("InterMezzo: cache mount failure.\n");
                MOD_DEC_USE_COUNT;
                EXIT;
                goto out_err;
        }

        cache->cache_sb = sb;
        cache->cache_root = dget(sb->s_root);

        /* we now know the dev of the cache: hash the cache */
        presto_cache_add(cache, sb->s_dev);
        err = izo_prepare_fileset(sb->s_root, fileset); 

        filter_setup_journal_ops(cache->cache_filter, cache->cache_type); 

        /* make sure we have our own super operations: sb
           still contains the cache operations */
        filter_setup_super_ops(cache->cache_filter, sb->s_op, 
                               &presto_super_ops);
        sb->s_op = filter_c2usops(cache->cache_filter);

        /* get izo directory operations: sb->s_root->d_inode exists now */
        filter_setup_dir_ops(cache->cache_filter, sb->s_root->d_inode,
                             &presto_dir_iops, &presto_dir_fops);
        filter_setup_dentry_ops(cache->cache_filter, sb->s_root->d_op, 
                                &presto_dentry_ops);
        sb->s_root->d_inode->i_op = filter_c2udiops(cache->cache_filter);
        sb->s_root->d_inode->i_fop = filter_c2udfops(cache->cache_filter);
        sb->s_root->d_op = filter_c2udops(cache->cache_filter);

        EXIT;
        return sb;

 out_err:
        CDEBUG(D_SUPER, "out_err called\n");
        if (cache)
                PRESTO_FREE(cache, sizeof(struct presto_cache));
        if (cache_data)
                PRESTO_FREE(cache_data, PAGE_SIZE);
        if (fileset)
                PRESTO_FREE(fileset, strlen(fileset) + 1);
        if (channel)
                PRESTO_FREE(channel, strlen(channel) + 1);
        if (cache_type)
                PRESTO_FREE(cache_type, strlen(cache_type) + 1);

        CDEBUG(D_MALLOC, "mount error exit: kmem %ld, vmem %ld\n",
               presto_kmemory, presto_vmemory);
        return NULL;
}