コード例 #1
0
ファイル: upcall.c プロジェクト: xricson/knoppix
static struct izo_upcall_hdr *upc_pack(__u32 opcode, int pathlen, char *path,
                                       char *fsetname, int reclen, char *rec,
                                       int *size)
{
        struct izo_upcall_hdr *hdr;
        char *ptr;
        ENTRY;

        *size = sizeof(struct izo_upcall_hdr);
        if ( fsetname ) {
                *size += round_strlen(fsetname);
        }
        if ( path ) { 
                *size += round_strlen(path);
        }
        if ( rec ) { 
                *size += size_round(reclen);
        }
        PRESTO_ALLOC(hdr, *size);
        if (!hdr) { 
                CERROR("intermezzo upcall: out of memory (opc %d)\n", opcode);
                EXIT;
                return NULL;
        }
        memset(hdr, 0, *size);

        ptr = (char *)hdr + sizeof(*hdr);

        /* XXX do we need fsuid ? */
        hdr->u_len = *size;
        hdr->u_version = IZO_UPC_VERSION;
        hdr->u_opc = opcode;
        hdr->u_pid = current->pid;
        hdr->u_uid = current->fsuid;

        if (path) { 
                /*XXX Robert: please review what len to pass in for 
                  NUL terminated strings */
                hdr->u_pathlen = strlen(path);
                LOGL0(path, hdr->u_pathlen, ptr);
        }
        if (fsetname) { 
                hdr->u_fsetlen = strlen(fsetname);
                LOGL0(fsetname, strlen(fsetname), ptr);
        }
        if (rec) { 
                hdr->u_reclen = reclen;
                LOGL(rec, reclen, ptr);
        }
        
        EXIT;
        return hdr;
}
コード例 #2
0
ファイル: presto.c プロジェクト: JBTech/ralink_rt5350
/* 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; 
        }
}
/* returns an allocated string, copied out from data if opt is found */
static char *opt_read(const char *opt, char *data)
{
        char *value;
        char *retval;

        CDEBUG(D_SUPER, "option: %s, data %s\n", opt, data);
        if ( strncmp(opt, data, strlen(opt)) )
                return NULL;

        if ( (value = strchr(data, '=')) == NULL )
                return NULL;

        value++;
        PRESTO_ALLOC(retval, strlen(value) + 1);
        if ( !retval ) {
                CERROR("InterMezzo: Out of memory!\n");
                return NULL;
        }

        strcpy(retval, value);
        CDEBUG(D_SUPER, "Assigned option: %s, value %s\n", opt, retval);
        return retval;
}
コード例 #5
0
ファイル: sysctl.c プロジェクト: JBTech/ralink_rt5350
/* 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;
}
コード例 #7
0
ファイル: ext_attr.c プロジェクト: JBTech/ralink_rt5350
/* 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;
}