Example #1
0
void cleanup_intermezzo_sysctl(void)
{
	int total_dev = MAX_CHANNEL;
	int entries_per_dev = sizeof(proto_psdev_table) /
		sizeof(proto_psdev_table[0]);
	int total_entries = entries_per_dev * total_dev;
	int i;

#ifdef CONFIG_SYSCTL
	if ( intermezzo_table_header )
		unregister_sysctl_table(intermezzo_table_header);
	intermezzo_table_header = NULL;
#endif
	for(i = 0; i < total_dev; i++) {
		/* entry for this /proc/sys/intermezzo/intermezzo"i" */
		ctl_table *psdev = &presto_table[i + PRESTO_PRIMARY_CTLCNT];
		PRESTO_FREE(psdev->procname, PROCNAME_SIZE);
	}
	/* presto_table[PRESTO_PRIMARY_CTLCNT].child points to the
	 * dev_ctl_table previously allocated in init_intermezzo_psdev()
	 */
	PRESTO_FREE(presto_table[PRESTO_PRIMARY_CTLCNT].child, sizeof(ctl_table) * total_entries);

#if CONFIG_PROC_FS
	remove_proc_entry("mounts", proc_fs_intermezzo);
	remove_proc_entry("intermezzo", proc_root_fs);
#endif
}
Example #2
0
int izo_upc_client_make_branch(int minor, char *fsetname, char *tagname,
                               char *branchname)
{
        int size, error;
        struct izo_upcall_hdr *hdr;
        int pathlen;
        char *path;
        ENTRY;

        hdr = upc_pack(IZO_UPC_CLIENT_MAKE_BRANCH, strlen(tagname), tagname,
                       fsetname, strlen(branchname) + 1, branchname, &size);
        if (!hdr || IS_ERR(hdr)) {
                error = -PTR_ERR(hdr);
                goto error;
        }

        error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
        if (error)
                CERROR("InterMezzo: error %d\n", error);

 error:
        PRESTO_FREE(path, pathlen);
        EXIT;
        return error;
}
static void opt_store(char **dst, char *opt)
{
        if (!dst) 
                CERROR("intermezzo: store_opt, error dst == NULL\n"); 

        if (*dst)
                PRESTO_FREE(*dst, strlen(*dst) + 1);
        *dst = opt;
}
Example #4
0
void presto_put_super(struct super_block *sb)
{
        struct presto_cache *cache;
        struct upc_comm *psdev;
        struct super_operations *sops;
        struct list_head *lh;

	ENTRY;
        cache = presto_find_cache(sb->s_dev);
        if (!cache) {
		EXIT;
                goto exit;
	}
        psdev = &upc_comms[presto_c2m(cache)];

        sops = filter_c2csops(cache->cache_filter);
        if (sops->put_super)
                sops->put_super(sb);

        /* free any remaining async upcalls when the filesystem is unmounted */
        lh = psdev->uc_pending.next;
        while ( lh != &psdev->uc_pending) {
                struct upc_req *req;
                req = list_entry(lh, struct upc_req, rq_chain);

                /* assignment must be here: we are about to free &lh */
                lh = lh->next;
                if ( ! (req->rq_flags & REQ_ASYNC) ) 
                        continue;
                list_del(&(req->rq_chain));
                PRESTO_FREE(req->rq_data, req->rq_bufsize);
                PRESTO_FREE(req, sizeof(struct upc_req));
        }

        presto_free_cache(cache);

exit:
        CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n",
               presto_kmemory, presto_vmemory);
        MOD_DEC_USE_COUNT;
        return ;
}
Example #5
0
/* talk to Lento about the permit */
static int presto_permit_upcall(struct dentry *dentry)
{
        int rc;
        char *path, *buffer;
        int pathlen;
        int minor;
        int fsetnamelen;
        struct presto_file_set *fset = NULL;

        ENTRY;

        if ( (minor = presto_i2m(dentry->d_inode)) < 0) {
                EXIT;
                return -EINVAL;
        }

        fset = presto_fset(dentry);
        if (!fset) {
                EXIT;
                return -ENOTCONN;
        }
        
        if ( !presto_lento_up(minor) ) {
                if ( fset->fset_flags & FSET_STEAL_PERMIT ) {
                        EXIT;
                        return 0;
                } else {
                        EXIT;
                        return -ENOTCONN;
                }
        }

        PRESTO_ALLOC(buffer, PAGE_SIZE);
        if ( !buffer ) {
                CERROR("PRESTO: out of memory!\n");
                EXIT;
                return -ENOMEM;
        }
        path = presto_path(dentry, fset->fset_dentry, buffer, PAGE_SIZE);
        pathlen = MYPATHLEN(buffer, path);
        fsetnamelen = strlen(fset->fset_name); 
        rc = izo_upc_permit(minor, dentry, pathlen, path, fset->fset_name);
        PRESTO_FREE(buffer, PAGE_SIZE);
        EXIT;
        return rc;
}
static void opt_set_default(char **dst, char *defval)
{
        if (!dst) 
                CERROR("intermezzo: store_opt, error dst == NULL\n"); 

        if (*dst)
                PRESTO_FREE(*dst, strlen(*dst) + 1);
        if (defval) {
                char *def_alloced; 
                PRESTO_ALLOC(def_alloced, strlen(defval)+1);
                if (!def_alloced) {
                        CERROR("InterMezzo: Out of memory!\n");
                        return ;
                }
                strcpy(def_alloced, defval);
                *dst = def_alloced; 
        }
}
Example #7
0
/* allocate the tables for the presto devices. We need
 * sizeof(proto_channel_table)/sizeof(proto_channel_table[0])
 * entries for each dev
 */
int /* __init */ init_intermezzo_sysctl(void)
{
	int i;
	int total_dev = MAX_CHANNEL;
	int entries_per_dev = sizeof(proto_psdev_table) /
		sizeof(proto_psdev_table[0]);
	int total_entries = entries_per_dev * total_dev;
	ctl_table *dev_ctl_table;

	PRESTO_ALLOC(dev_ctl_table, sizeof(ctl_table) * total_entries);

	if (! dev_ctl_table) {
		CERROR("WARNING: presto couldn't allocate dev_ctl_table\n");
		EXIT;
		return -ENOMEM;
	}

	/* now fill in the entries ... we put the individual presto<x>
	 * entries at the end of the table, and the per-presto stuff
	 * starting at the front.  We assume that the compiler makes
	 * this code more efficient, but really, who cares ... it
	 * happens once per reboot.
	 */
	for(i = 0; i < total_dev; i++) {
		void *p;

		/* entry for this /proc/sys/intermezzo/intermezzo"i" */
		ctl_table *psdev = &presto_table[i + PRESTO_PRIMARY_CTLCNT];
		/* entries for the individual "files" in this "directory" */
		ctl_table *psdev_entries = &dev_ctl_table[i * entries_per_dev];
		/* init the psdev and psdev_entries with the prototypes */
		*psdev = proto_channel_entry;
		memcpy(psdev_entries, proto_psdev_table,
		       sizeof(proto_psdev_table));
		/* now specialize them ... */
		/* the psdev has to point to psdev_entries, and fix the number */
		psdev->ctl_name = psdev->ctl_name + i + 1; /* sorry */

		PRESTO_ALLOC(p, PROCNAME_SIZE);
		psdev->procname = p;
		if (!psdev->procname) {
			PRESTO_FREE(dev_ctl_table,
				    sizeof(ctl_table) * total_entries);
			return -ENOMEM;
		}
		sprintf((char *) psdev->procname, "intermezzo%d", i);
		/* hook presto into */
		psdev->child = psdev_entries;

		/* now for each psdev entry ... */
		psdev_entries[0].data = &(izo_channels[i].uc_hard);
		psdev_entries[1].data = &(izo_channels[i].uc_no_filter);
		psdev_entries[2].data = &(izo_channels[i].uc_no_journal);
		psdev_entries[3].data = &(izo_channels[i].uc_no_upcall);
		psdev_entries[4].data = &(izo_channels[i].uc_timeout);
#ifdef PRESTO_DEBUG
		psdev_entries[5].data = &(izo_channels[i].uc_errorval);
#endif
	}


#ifdef CONFIG_SYSCTL
	if ( !intermezzo_table_header )
		intermezzo_table_header =
			register_sysctl_table(intermezzo_table, 0);
#endif
#ifdef CONFIG_PROC_FS
	proc_fs_intermezzo = proc_mkdir("intermezzo", proc_root_fs);
	proc_fs_intermezzo->owner = THIS_MODULE;
	create_proc_info_entry("mounts", 0, proc_fs_intermezzo, 
			       intermezzo_mount_get_info);
#endif
	return 0;
}
/* 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;
}
Example #9
0
/* XXX! Fixme test for user defined attributes */
int presto_set_ext_attr(struct inode *inode, 
                        const char *name, void *buffer,
                        size_t buffer_len, int flags) 
{
        int error;
        struct presto_cache *cache;
        struct presto_file_set *fset;
        struct lento_vfs_context info;
        struct dentry *dentry;
        int minor = presto_i2m(inode);
        char *buf = NULL;

        ENTRY;
        if (minor < 0) {
                EXIT;
                return -1;
        }

        if ( ISLENTO(minor) ) {
                EXIT;
                return -EINVAL;
        }

        /* BAD...vfs should really pass down the dentry to use, especially
         * since every other operation in iops does. But for now
         * we do a reverse mapping from inode to the first dentry 
         */
        if (list_empty(&inode->i_dentry)) {
                CERROR("No alias for inode %d\n", (int) inode->i_ino);
                EXIT;
                return -EINVAL;
        }

        dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);

        error = presto_prep(dentry, &cache, &fset);
        if ( error ) {
                EXIT;
                return error;
        }

        if ((buffer != NULL) && (buffer_len != 0)) {
            /* If buffer is a user space pointer copy it to kernel space
            * and reset the flag. We do this since the journal functions need
            * access to the contents of the buffer, and the file system
            * does not care. When we actually invoke the function, we remove
            * the EXT_ATTR_FLAG_USER flag.
            *
            * XXX:Check if the "fs does not care" assertion is always true -SHP
            * (works for ext3)
            */
            if (flags & EXT_ATTR_FLAG_USER) {
                PRESTO_ALLOC(buf, buffer_len);
                if (!buf) {
                        CERROR("InterMezzo: out of memory!!!\n");
                        return -ENOMEM;
                }
                error = copy_from_user(buf, buffer, buffer_len);
                if (error) 
                        return -EFAULT;
            } else 
                buf = buffer;
        } else
                buf = buffer;

        if ( presto_get_permit(inode) < 0 ) {
                EXIT;
                if (buffer_len && (flags & EXT_ATTR_FLAG_USER))
                        PRESTO_FREE(buf, buffer_len);
                return -EROFS;
        }

        /* Simulate presto_setup_info */
        memset(&info, 0, sizeof(info));
        /* For now redundant..but we keep it around just in case */
        info.flags = LENTO_FL_IGNORE_TIME;
        if (!ISLENTO(cache->cache_psdev->uc_minor))
            info.flags |= LENTO_FL_KML;

        /* We pass in the kernel space pointer and reset the 
         * EXT_ATTR_FLAG_USER flag.
         * See comments above. 
         */ 
        /* Note that mode is already set by VFS so we send in a NULL */
        error = presto_do_set_ext_attr(fset, dentry, name, buf,
                                       buffer_len, flags & ~EXT_ATTR_FLAG_USER,
                                       NULL, &info);
        presto_put_permit(inode);

        if (buffer_len && (flags & EXT_ATTR_FLAG_USER))
                PRESTO_FREE(buf, buffer_len);
        EXIT;
        return error;
}
Example #10
0
static void presto_put_super(struct super_block *sb)
{
        struct presto_cache *cache;
        struct upc_channel *channel;
        struct super_operations *sops;
        struct list_head *lh;
        int err;

        ENTRY;
        cache = presto_cache_find(sb->s_dev);
        if (!cache) {
                EXIT;
                goto exit;
        }
        channel = &izo_channels[presto_c2m(cache)];
        sops = filter_c2csops(cache->cache_filter);
        err = izo_clear_all_fsetroots(cache); 
        if (err) { 
                CERROR("%s: err %d\n", __FUNCTION__, err);
        }
        PRESTO_FREE(cache->cache_vfsmount, sizeof(struct vfsmount));

        /* look at kill_super - fsync_super is not exported GRRR but 
           probably not needed */ 
        unlock_super(sb);
        shrink_dcache_parent(cache->cache_root); 
        dput(cache->cache_root); 
        //fsync_super(sb); 
        lock_super(sb);

        if (sops->write_super)
                sops->write_super(sb); 

        if (sops->put_super)
                sops->put_super(sb);

        /* free any remaining async upcalls when the filesystem is unmounted */
        spin_lock(&channel->uc_lock);
        lh = channel->uc_pending.next;
        while ( lh != &channel->uc_pending) {
                struct upc_req *req;
                req = list_entry(lh, struct upc_req, rq_chain);

                /* assignment must be here: we are about to free &lh */
                lh = lh->next;
                if ( ! (req->rq_flags & REQ_ASYNC) ) 
                        continue;
                list_del(&(req->rq_chain));
                PRESTO_FREE(req->rq_data, req->rq_bufsize);
                PRESTO_FREE(req, sizeof(struct upc_req));
        }
        list_del(&cache->cache_channel_list); 
        spin_unlock(&channel->uc_lock);

        presto_free_cache(cache);

exit:
        CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n",
               presto_kmemory, presto_vmemory);
        MOD_DEC_USE_COUNT;
        return ;
}