Beispiel #1
0
static struct super_block *jffs2_get_sb(struct file_system_type *fs_type,
					int flags, const char *dev_name,
					void *data)
{
	int err;
	struct nameidata nd;
	int mtdnr;

	if (!dev_name)
		return ERR_PTR(-EINVAL);

	D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name));

	/* The preferred way of mounting in future; especially when
	   CONFIG_BLK_DEV is implemented - we specify the underlying
	   MTD device by number or by name, so that we don't require 
	   block device support to be present in the kernel. */

	/* FIXME: How to do the root fs this way? */

	if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') {
		/* Probably mounting without the blkdev crap */
		if (dev_name[3] == ':') {
			struct mtd_info *mtd;

			/* Mount by MTD device name */
			D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4));
			for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) {
				mtd = get_mtd_device(NULL, mtdnr);
				if (mtd) {
					if (!strcmp(mtd->name, dev_name+4))
						return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd);
					put_mtd_device(mtd);
				}
			}
			printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4);
		} else if (isdigit(dev_name[3])) {
			/* Mount by MTD device number name */
			char *endptr;
			
			mtdnr = simple_strtoul(dev_name+3, &endptr, 0);
			if (!*endptr) {
				/* It was a valid number */
				D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr));
				return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr);
			}
		}
	}

	/* Try the old way - the hack where we allowed users to mount 
	   /dev/mtdblock$(n) but didn't actually _use_ the blkdev */

	err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);

	D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n",
		  err, nd.dentry->d_inode));

	if (err)
		return ERR_PTR(err);

	err = -EINVAL;

	if (!S_ISBLK(nd.dentry->d_inode->i_mode))
		goto out;

	if (nd.mnt->mnt_flags & MNT_NODEV) {
		err = -EACCES;
		goto out;
	}

	if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) {
		if (!(flags & MS_VERBOSE)) /* Yes I mean this. Strangely */
			printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n",
			       dev_name);
		goto out;
	}

	mtdnr = iminor(nd.dentry->d_inode);
	path_release(&nd);

	return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr);

out:
	path_release(&nd);
	return ERR_PTR(err);
}
Beispiel #2
0
/*
 * parse the dirs= mount argument
 *
 * We don't need to lock the superblock private data's rwsem, as we get
 * called only by unionfs_read_super - it is still a long time before anyone
 * can even get a reference to us.
 */
static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info
                             *lower_root_info, char *options)
{
    struct nameidata nd;
    char *name;
    int err = 0;
    int branches = 1;
    int bindex = 0;
    int i = 0;
    int j = 0;
    struct dentry *dent1;
    struct dentry *dent2;

    if (options[0] == '\0') {
        printk(KERN_ERR "unionfs: no branches specified\n");
        err = -EINVAL;
        goto out;
    }

    /*
     * Each colon means we have a separator, this is really just a rough
     * guess, since strsep will handle empty fields for us.
     */
    for (i = 0; options[i]; i++)
        if (options[i] == ':')
            branches++;

    /* allocate space for underlying pointers to lower dentry */
    UNIONFS_SB(sb)->data =
        kcalloc(branches, sizeof(struct unionfs_data), GFP_KERNEL);
    if (unlikely(!UNIONFS_SB(sb)->data)) {
        err = -ENOMEM;
        goto out;
    }

    lower_root_info->lower_paths =
        kcalloc(branches, sizeof(struct path), GFP_KERNEL);
    if (unlikely(!lower_root_info->lower_paths)) {
        err = -ENOMEM;
        goto out;
    }

    /* now parsing a string such as "b1:b2=rw:b3=ro:b4" */
    branches = 0;
    while ((name = strsep(&options, ":")) != NULL) {
        int perms;
        char *mode = strchr(name, '=');

        if (!name)
            continue;
        if (!*name) {	/* bad use of ':' (extra colons) */
            err = -EINVAL;
            goto out;
        }

        branches++;

        /* strip off '=' if any */
        if (mode)
            *mode++ = '\0';

        err = parse_branch_mode(mode, &perms);
        if (err) {
            printk(KERN_ERR "unionfs: invalid mode \"%s\" for "
                   "branch %d\n", mode, bindex);
            goto out;
        }
        /* ensure that leftmost branch is writeable */
        if (!bindex && !(perms & MAY_WRITE)) {
            printk(KERN_ERR "unionfs: leftmost branch cannot be "
                   "read-only (use \"-o ro\" to create a "
                   "read-only union)\n");
            err = -EINVAL;
            goto out;
        }

        err = path_lookup(name, LOOKUP_FOLLOW, &nd);
        if (err) {
            printk(KERN_ERR "unionfs: error accessing "
                   "lower directory '%s' (error %d)\n",
                   name, err);
            goto out;
        }

        err = check_branch(&nd);
        if (err) {
            printk(KERN_ERR "unionfs: lower directory "
                   "'%s' is not a valid branch\n", name);
            path_release(&nd);
            goto out;
        }

        lower_root_info->lower_paths[bindex].dentry = nd.dentry;
        lower_root_info->lower_paths[bindex].mnt = nd.mnt;

        set_branchperms(sb, bindex, perms);
        set_branch_count(sb, bindex, 0);
        new_branch_id(sb, bindex);

        if (lower_root_info->bstart < 0)
            lower_root_info->bstart = bindex;
        lower_root_info->bend = bindex;
        bindex++;
    }

    if (branches == 0) {
        printk(KERN_ERR "unionfs: no branches specified\n");
        err = -EINVAL;
        goto out;
    }

    BUG_ON(branches != (lower_root_info->bend + 1));

    /*
     * Ensure that no overlaps exist in the branches.
     *
     * This test is required because the Linux kernel has no support
     * currently for ensuring coherency between stackable layers and
     * branches.  If we were to allow overlapping branches, it would be
     * possible, for example, to delete a file via one branch, which
     * would not be reflected in another branch.  Such incoherency could
     * lead to inconsistencies and even kernel oopses.  Rather than
     * implement hacks to work around some of these cache-coherency
     * problems, we prevent branch overlapping, for now.  A complete
     * solution will involve proper kernel/VFS support for cache
     * coherency, at which time we could safely remove this
     * branch-overlapping test.
     */
    for (i = 0; i < branches; i++) {
        dent1 = lower_root_info->lower_paths[i].dentry;
        for (j = i + 1; j < branches; j++) {
            dent2 = lower_root_info->lower_paths[j].dentry;
            if (is_branch_overlap(dent1, dent2)) {
                printk(KERN_ERR "unionfs: branches %d and "
                       "%d overlap\n", i, j);
                err = -EINVAL;
                goto out;
            }
        }
    }

out:
    if (err) {
        for (i = 0; i < branches; i++)
            if (lower_root_info->lower_paths[i].dentry) {
                dput(lower_root_info->lower_paths[i].dentry);
                /* initialize: can't use unionfs_mntput here */
                mntput(lower_root_info->lower_paths[i].mnt);
            }

        kfree(lower_root_info->lower_paths);
        kfree(UNIONFS_SB(sb)->data);

        /*
         * MUST clear the pointers to prevent potential double free if
         * the caller dies later on
         */
        lower_root_info->lower_paths = NULL;
        UNIONFS_SB(sb)->data = NULL;
    }
    return err;
}
Beispiel #3
0
int file_mkdir(const char * pathname, unsigned short perms, int recurse) {
    /* Welcome to the jungle... */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,41)
    /* DO NOT REFERENCE THIS VARIABLE */
    /* It only exists to provide version compatibility */
    struct path tmp_path;
#endif

    struct path * path_ptr = NULL;
    struct dentry * dentry;
    int ret = 0;



    if (recurse != 0) {
        return mkdir_recursive(pathname, perms);
    }

    /* Before Linux 3.1 this was somewhat more difficult */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,41)
    {
        struct nameidata nd;

        // I'm not 100% sure about the version here, but it was around this time that the API changed
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38)
        ret = kern_path_parent(pathname, &nd);
#else

        if (path_lookup(pathname, LOOKUP_DIRECTORY | LOOKUP_FOLLOW, &nd) == 0) {
            return 0;
        }

        if (path_lookup(pathname, LOOKUP_PARENT | LOOKUP_FOLLOW, &nd) != 0) {
            return -1;
        }
#endif

        if (ret != 0) {
            printk(KERN_ERR "%s:%d - Error: kern_path_parent() returned error for (%s)\n", __FILE__, __LINE__,
                   pathname);
            return -1;
        }

        dentry = lookup_create(&nd, 1);
        path_ptr = &(nd.path);
    }
#else
    {
        dentry = kern_path_create(AT_FDCWD, pathname, &tmp_path, 1);

        if (IS_ERR(dentry)) {
            return 0;
        }

        path_ptr = &tmp_path;
    }
#endif


    if (!IS_ERR(dentry)) {
        ret = vfs_mkdir(path_ptr->dentry->d_inode, dentry, perms);
    }

    mutex_unlock(&(path_ptr->dentry->d_inode->i_mutex));
    path_put(path_ptr);

    return ret;
}
Beispiel #4
0
static int
bind_unix_socket(struct socket *sock, struct cpt_sock_image *si,
                 cpt_context_t *ctx)
{
    int err;
    char *name;
    struct sockaddr* addr;
    int addrlen;
    struct sockaddr_un sun;
    struct nameidata nd;

    if ((addrlen = si->cpt_laddrlen) <= 2)
        return 0;

    nd.path.dentry = NULL;
    name = ((char*)si->cpt_laddr) + 2;
    addr = (struct sockaddr *)si->cpt_laddr;

    if (name[0]) {
        if (path_lookup(name, 0, &nd))
            nd.path.dentry = NULL;

        if (si->cpt_deleted) {
            if (nd.path.dentry == NULL &&
                    sock->ops->bind(sock, addr, addrlen) == 0) {
                sc_unlink(name);
                return 0;
            }

            addr = (struct sockaddr*)&sun;
            addr->sa_family = AF_UNIX;
            name = ((char*)addr) + 2;
            err = select_deleted_name(name, ctx);
            if (err)
                goto out;
            addrlen = 2 + strlen(name);
        } else if (nd.path.dentry) {
            if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode)) {
                eprintk_ctx("bind_unix_socket: not a socket dentry\n");
                err = -EINVAL;
                goto out;
            }
            sc_unlink(name);
        }
    }

    err = sock->ops->bind(sock, addr, addrlen);

    if (!err && name[0]) {
        if (nd.path.dentry) {
            sc_chown(name, nd.path.dentry->d_inode->i_uid,
                     nd.path.dentry->d_inode->i_gid);
            sc_chmod(name, nd.path.dentry->d_inode->i_mode);
        }
        if (si->cpt_deleted)
            sc_unlink(name);
    }

out:
    if (nd.path.dentry)
        path_put(&nd.path);
    return err;
}
Beispiel #5
0
int main(int argc, char **argv)	
{
	int ret = -1;
	int count;
	char *mybuffer, *verify_buffer;
	int i;
	char path_name[PATH_SIZE];
	TROVE_op_id op_id;
	TROVE_coll_id coll_id;
	TROVE_handle file_handle, parent_handle;
	TROVE_ds_state state;
	char *file_name;
	TROVE_keyval_s key, val;
        TROVE_context_id trove_context = -1;

	char *mem_offset_array[4] = {0};
	TROVE_size mem_size_array[4] = { 5*MB, 5*MB, 5*MB, 5*MB };
	int mem_count = 4;
	TROVE_offset stream_offset_array[1] = {0};
	TROVE_size stream_size_array[1] = { 20*MB };
	int stream_count = 1;
	TROVE_size output_size;
	void *user_ptr_array[1] = { (char *) 13 };
        int test_failed = 0;

        TROVE_extent cur_extent;
        TROVE_handle_extent_array extent_array;

	/*************************************************************/
	/* initialization stuff */

	ret = trove_initialize(
	    TROVE_METHOD_DBPF, NULL, storage_space, storage_space, 0);
	if (ret < 0) {
	    fprintf(stderr, "initialize failed: run trove-mkfs first.\n");
	    return -1;
	}

	/* try to look up collection used to store file system */
	ret = trove_collection_lookup(
	    TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id);
	if (ret < 0) {
	    fprintf(stderr, "collection lookup failed.\n");
	    return -1;
	}

        ret = trove_open_context(coll_id, &trove_context);
        if (ret < 0)
        {
            fprintf(stderr, "trove_open_context failed\n");
            return -1;
        }

	/* find the parent directory name */
	strcpy(path_name, path_to_file);
	for (i=strlen(path_name); i >= 0; i--) {
	    if (path_name[i] != '/') path_name[i] = '\0';
	    else break;
	}
	file_name = path_to_file + strlen(path_name);
	printf("path is %s\n", path_name);
	printf("file is %s\n", file_name);

        /* find the parent directory handle */
	ret = path_lookup(coll_id, trove_context, path_name, &parent_handle);
	if (ret < 0) {
	    return -1;
	}

	file_handle = 0;

        cur_extent.first = cur_extent.last = requested_file_handle;
        extent_array.extent_count = 1;
        extent_array.extent_array = &cur_extent;
	ret = trove_dspace_create(coll_id,
                                  &extent_array,
				  &file_handle,
				  TROVE_TEST_FILE,
				  NULL,
				  TROVE_FORCE_REQUESTED_HANDLE,
				  NULL,
                                  trove_context,
				  &op_id,
                                  NULL);
	while (ret == 0) ret = trove_dspace_test(
            coll_id, op_id, trove_context, &count, NULL, NULL, &state,
            TROVE_DEFAULT_TEST_TIMEOUT);
	if (ret < 0) {
	    fprintf(stderr, "dspace create failed.\n");
	    return -1;
	}

	/* TODO: set attributes of file? */

	/* add new file name/handle pair to parent directory */
	key.buffer = file_name;
	key.buffer_sz = strlen(file_name) + 1;
	val.buffer = &file_handle;
	val.buffer_sz = sizeof(file_handle);
	ret = trove_keyval_write(coll_id, parent_handle, &key, &val,
                                 0, NULL, NULL, trove_context, &op_id, NULL);
	while (ret == 0) ret = trove_dspace_test(
            coll_id, op_id, trove_context, &count, NULL, NULL, &state,
            TROVE_DEFAULT_TEST_TIMEOUT);
	if (ret < 0) {
	    fprintf(stderr, "keyval write failed.\n");
	    return -1;
	}

	/* memory buffer to xfer */
	mybuffer = (char *)malloc(TEST_SIZE);
	if (!mybuffer)
	{
            fprintf(stderr, "mem.\n");
            return(-1);
	}
	verify_buffer = (char *)malloc(TEST_SIZE);
	if (!verify_buffer)
	{
            fprintf(stderr, "mem.\n");
            return(-1);
	}

	mem_offset_array[0] = mybuffer;
	mem_offset_array[2] = (mem_offset_array[0] + 5*MB);
	mem_offset_array[1] = (mem_offset_array[2] + 5*MB);
	mem_offset_array[3] = (mem_offset_array[1] + 5*MB);

        memset(mem_offset_array[0], 0xFE, 5*MB);
        memset(mem_offset_array[1], 0xFD, 5*MB);
        memset(mem_offset_array[2], 0xFC, 5*MB);
        memset(mem_offset_array[3], 0xFB, 5*MB);

	/********************************/

	ret = trove_bstream_write_list(coll_id,
				       parent_handle,
				       mem_offset_array,
				       mem_size_array,
				       mem_count,
				       stream_offset_array,
				       stream_size_array,
				       stream_count,
				       &output_size,
				       0, /* flags */
				       NULL, /* vtag */
				       user_ptr_array,
                                       trove_context,
				       &op_id,
                                       NULL);
	while (ret == 0) ret = trove_dspace_test(
            coll_id, op_id, trove_context, &count, NULL, NULL, &state,
            TROVE_DEFAULT_TEST_TIMEOUT);
	if (ret < 0) {
	    fprintf(stderr, "listio write failed\n");
	    return -1;
	}

	mem_offset_array[0] = verify_buffer;
	mem_offset_array[2] = (mem_offset_array[0] + 5*MB);
	mem_offset_array[1] = (mem_offset_array[2] + 5*MB);
	mem_offset_array[3] = (mem_offset_array[1] + 5*MB);

        memset(mem_offset_array[0], 0xDE, 5*MB);
        memset(mem_offset_array[1], 0xDD, 5*MB);
        memset(mem_offset_array[2], 0xDC, 5*MB);
        memset(mem_offset_array[3], 0xDB, 5*MB);

        /* should read this back out and verify here */
	ret = trove_bstream_read_list(coll_id,
                                      parent_handle,
                                      mem_offset_array,
                                      mem_size_array,
                                      mem_count,
                                      stream_offset_array,
                                      stream_size_array,
                                      stream_count,
                                      &output_size,
                                      0, /* flags */
                                      NULL, /* vtag */
                                      user_ptr_array,
                                      trove_context,
                                      &op_id,
                                      NULL);
	while (ret == 0) ret = trove_dspace_test(
            coll_id, op_id, trove_context, &count, NULL, NULL, &state,
            TROVE_DEFAULT_TEST_TIMEOUT);
	if (ret < 0)
        {
	    fprintf(stderr, "listio read failed\n");
	    return -1;
	}

        for(i = 0; i < TEST_SIZE; i++)
        {
            if (mybuffer[i] != verify_buffer[i])
            {
                fprintf(stderr,"data mismatch at index %d (%x != %x)\n",
                        i,mybuffer[i],verify_buffer[i]);
                test_failed = 1;
                break;
            }
/*             fprintf(stderr,"data match at index %d (%x == %x)\n", */
/*                     i,mybuffer[i],verify_buffer[i]); */
        }

        free(mybuffer);
        free(verify_buffer);

        fprintf(stderr,"This bstream listio test %s\n",
                (test_failed ? "failed miserably" : "passed"));

        trove_close_context(coll_id, trove_context);
	trove_finalize(TROVE_METHOD_DBPF);
	return 0;
}
Beispiel #6
0
static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
{
	/* client fsidtype fsid [path] */
	char *buf;
	int len;
	struct auth_domain *dom = NULL;
	int err;
	int fsidtype;
	char *ep;
	struct svc_expkey key;

	if (mesg[mlen-1] != '\n')
		return -EINVAL;
	mesg[mlen-1] = 0;

	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
	err = -ENOMEM;
	if (!buf) goto out;

	err = -EINVAL;
	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
		goto out;

	err = -ENOENT;
	dom = auth_domain_find(buf);
	if (!dom)
		goto out;
	dprintk("found domain %s\n", buf);

	err = -EINVAL;
	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
		goto out;
	fsidtype = simple_strtoul(buf, &ep, 10);
	if (*ep)
		goto out;
	dprintk("found fsidtype %d\n", fsidtype);
	if (fsidtype > 2)
		goto out;
	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
		goto out;
	dprintk("found fsid length %d\n", len);
	if (len != key_len(fsidtype))
		goto out;

	/* OK, we seem to have a valid key */
	key.h.flags = 0;
	key.h.expiry_time = get_expiry(&mesg);
	if (key.h.expiry_time == 0)
		goto out;

	key.ek_client = dom;	
	key.ek_fsidtype = fsidtype;
	memcpy(key.ek_fsid, buf, len);

	/* now we want a pathname, or empty meaning NEGATIVE  */
	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0)
		goto out;
	dprintk("Path seems to be <%s>\n", buf);
	err = 0;
	if (len == 0) {
		struct svc_expkey *ek;
		set_bit(CACHE_NEGATIVE, &key.h.flags);
		ek = svc_expkey_lookup(&key, 1);
		if (ek)
			expkey_put(&ek->h, &svc_expkey_cache);
	} else {
		struct nameidata nd;
		struct svc_expkey *ek;
		struct svc_export *exp;
		err = path_lookup(buf, 0, &nd);
		if (err)
			goto out;

		dprintk("Found the path %s\n", buf);
		exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);

		err = -ENOENT;
		if (!exp)
			goto out_nd;
		key.ek_export = exp;
		dprintk("And found export\n");
		
		ek = svc_expkey_lookup(&key, 1);
		if (ek)
			expkey_put(&ek->h, &svc_expkey_cache);
		exp_put(exp);
		err = 0;
	out_nd:
		path_release(&nd);
	}
	cache_flush();
 out:
	if (dom)
		auth_domain_put(dom);
	if (buf)
		kfree(buf);
	return err;
}
Beispiel #7
0
int main(int argc, char **argv)	
{
	int ret = -1;
	int count;
	void* mybuffer;
	int i;
	char path_name[PATH_SIZE];
	TROVE_op_id op_id;
	TROVE_coll_id coll_id;
	TROVE_handle file_handle, parent_handle;
	TROVE_ds_state state;
	char *file_name;
	TROVE_keyval_s key, val;
        TROVE_context_id trove_context = -1;

	char *mem_offset_array[1];
	TROVE_size mem_size_array[1] = { 4*1048576 };
	int mem_count = 1;
	TROVE_offset stream_offset_array[1] = { 0 };
	TROVE_size stream_size_array[1] = { 4*1048576 };
	int stream_count = 1;
	TROVE_size output_size;
	void *user_ptr_array[1] = { (char *) 13 };

        TROVE_extent cur_extent;
        TROVE_handle_extent_array extent_array;

	/*************************************************************/
	/* initialization stuff */

	ret = trove_initialize(
	    TROVE_METHOD_DBPF, NULL, storage_space, 0);
	if (ret < 0) {
	    fprintf(stderr, "initialize failed: run trove-mkfs first.\n");
	    return -1;
	}

	/* try to look up collection used to store file system */
	ret = trove_collection_lookup(
	    TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id);
	if (ret < 0) {
	    fprintf(stderr, "collection lookup failed.\n");
	    return -1;
	}

        ret = trove_open_context(coll_id, &trove_context);
        if (ret < 0)
        {
            fprintf(stderr, "trove_open_context failed\n");
            return -1;
        }

	/* find the parent directory name */
	strcpy(path_name, path_to_file);
	for (i=strlen(path_name); i >= 0; i--) {
	    if (path_name[i] != '/') path_name[i] = '\0';
	    else break;
	}
	file_name = path_to_file + strlen(path_name);
	printf("path is %s\n", path_name);
	printf("file is %s\n", file_name);

    /* find the parent directory handle */
	ret = path_lookup(coll_id, trove_context, path_name, &parent_handle);
	if (ret < 0) {
	    return -1;
	}

	file_handle = 0;

        cur_extent.first = cur_extent.last = requested_file_handle;
        extent_array.extent_count = 1;
        extent_array.extent_array = &cur_extent;
	ret = trove_dspace_create(coll_id,
                                  &extent_array,
				  &file_handle,
				  TROVE_TEST_FILE,
				  NULL,
				  TROVE_FORCE_REQUESTED_HANDLE,
				  NULL,
                                  trove_context,
				  &op_id,
                                  NULL);
	while (ret == 0) ret = trove_dspace_test(
            coll_id, op_id, trove_context, &count, NULL, NULL, &state,
            TROVE_DEFAULT_TEST_TIMEOUT);
	if (ret < 0) {
	    fprintf(stderr, "dspace create failed.\n");
	    return -1;
	}

	/* TODO: set attributes of file? */

	/* add new file name/handle pair to parent directory */
	key.buffer = file_name;
	key.buffer_sz = strlen(file_name) + 1;
	val.buffer = &file_handle;
	val.buffer_sz = sizeof(file_handle);
	ret = trove_keyval_write(coll_id, parent_handle, &key, &val,
                                 0, NULL, NULL, trove_context, &op_id,
                                 NULL);
	while (ret == 0) ret = trove_dspace_test(
            coll_id, op_id, trove_context, &count, NULL, NULL, &state,
            TROVE_DEFAULT_TEST_TIMEOUT);
	if (ret < 0) {
	    fprintf(stderr, "keyval write failed.\n");
	    return -1;
	}

	/* memory buffer to xfer */
	mybuffer = (void*)malloc(TEST_SIZE);
	if(!mybuffer)
	{
		fprintf(stderr, "mem.\n");
		return(-1);
	}
	memset(mybuffer, 0, TEST_SIZE);

	mem_offset_array[0] = mybuffer;

	/********************************/

	ret = trove_bstream_write_list(coll_id,
				       parent_handle,
				       mem_offset_array,
				       mem_size_array,
				       mem_count,
				       stream_offset_array,
				       stream_size_array,
				       stream_count,
				       &output_size,
				       0, /* flags */
				       NULL, /* vtag */
				       user_ptr_array,
                                       trove_context,
				       &op_id,
                                       NULL);
	while (ret == 0) ret = trove_dspace_test(
            coll_id, op_id, trove_context, &count, NULL, NULL, &state,
            TROVE_DEFAULT_TEST_TIMEOUT);
	if (ret < 0) {
	    fprintf(stderr, "listio write failed\n");
	    return -1;
	}

        trove_close_context(coll_id, trove_context);
	trove_finalize(TROVE_METHOD_DBPF);
	return 0;
}
Beispiel #8
0
/*
 * Check if the given path is a mountpoint.
 *
 * If we are supplied with the file descriptor of an autofs
 * mount we're looking for a specific mount. In this case
 * the path is considered a mountpoint if it is itself a
 * mountpoint or contains a mount, such as a multi-mount
 * without a root mount. In this case we return 1 if the
 * path is a mount point and the super magic of the covering
 * mount if there is one or 0 if it isn't a mountpoint.
 *
 * If we aren't supplied with a file descriptor then we
 * lookup the nameidata of the path and check if it is the
 * root of a mount. If a type is given we are looking for
 * a particular autofs mount and if we don't find a match
 * we return fail. If the located nameidata path is the
 * root of a mount we return 1 along with the super magic
 * of the mount or 0 otherwise.
 *
 * In both cases the the device number (as returned by
 * new_encode_dev()) is also returned.
 */
static int autofs_dev_ioctl_ismountpoint(struct file *fp,
					 struct autofs_sb_info *sbi,
					 struct autofs_dev_ioctl *param)
{
	struct nameidata nd;
	const char *path;
	unsigned int type;
	int err = -ENOENT;

	if (param->size <= sizeof(*param)) {
		err = -EINVAL;
		goto out;
	}

	path = param->path;
	type = param->arg1;

	param->arg1 = 0;
	param->arg2 = 0;

	if (!fp || param->ioctlfd == -1) {
		if (type == AUTOFS_TYPE_ANY) {
			struct super_block *sb;

			err = path_lookup(path, LOOKUP_FOLLOW, &nd);
			if (err)
				goto out;

			sb = nd.path.dentry->d_sb;
			param->arg1 = new_encode_dev(sb->s_dev);
		} else {
			struct autofs_info *ino;

			err = path_lookup(path, LOOKUP_PARENT, &nd);
			if (err)
				goto out;

			err = autofs_dev_ioctl_find_sbi_type(&nd, type);
			if (err)
				goto out_release;

			ino = autofs4_dentry_ino(nd.path.dentry);
			param->arg1 = autofs4_get_dev(ino->sbi);
		}

		err = 0;
		if (nd.path.dentry->d_inode &&
		    nd.path.mnt->mnt_root == nd.path.dentry) {
			err = 1;
			param->arg2 = nd.path.dentry->d_inode->i_sb->s_magic;
		}
	} else {
		dev_t devid = new_encode_dev(sbi->sb->s_dev);

		err = path_lookup(path, LOOKUP_PARENT, &nd);
		if (err)
			goto out;

		err = autofs_dev_ioctl_find_super(&nd, devid);
		if (err)
			goto out_release;

		param->arg1 = autofs4_get_dev(sbi);

		err = have_submounts(nd.path.dentry);

		if (nd.path.mnt->mnt_mountpoint != nd.path.mnt->mnt_root) {
			if (follow_down(&nd.path.mnt, &nd.path.dentry)) {
				struct inode *inode = nd.path.dentry->d_inode;
				param->arg2 = inode->i_sb->s_magic;
			}
		}
	}

out_release:
	path_put(&nd.path);
out:
	return err;
}
Beispiel #9
0
int main(int argc, char **argv)
{
    int ret, count, i, myuid, mygid;
    TROVE_op_id op_id;
    TROVE_coll_id coll_id;
    TROVE_handle file_handle, parent_handle;
    TROVE_ds_state state;
    TROVE_keyval_s key, val;
    TROVE_ds_attributes_s s_attr;
    char *file_name;
    char path_name[PATH_SIZE];
    time_t mytime;
    TROVE_extent cur_extent;
    TROVE_handle_extent_array extent_array;
    TROVE_context_id trove_context = -1;

    ret = parse_args(argc, argv);
    if (ret < 0) {
	fprintf(stderr, "argument parsing failed.\n");
	return -1;
    }

    ret = trove_initialize(
        TROVE_METHOD_DBPF, NULL, storage_space, 0);
    if (ret < 0) {
	fprintf(stderr, "initialize failed.\n");
	return -1;
    }

    /* try to look up collection used to store file system */
    ret = trove_collection_lookup(
        TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id);
    if (ret < 0) {
	fprintf(stderr, "collection lookup failed.\n");
	return -1;
    }

    ret = trove_open_context(coll_id, &trove_context);
    if (ret < 0)
    {
        fprintf(stderr, "trove_open_context failed\n");
        return -1;
    }

    myuid = getuid();
    mygid = getgid();
    mytime = time(NULL);

    /* find the parent directory name */
    strcpy(path_name, path_to_file);
    for (i=strlen(path_name); i >= 0; i--) {
	if (path_name[i] != '/') path_name[i] = '\0';
	else break;
    }
    file_name = path_to_file + strlen(path_name);
#if 0
    printf("path is %s\n", path_name);
    printf("file is %s\n", file_name);
#endif

    /* find the parent directory handle */
    ret = path_lookup(coll_id, path_name, &parent_handle);
    if (ret < 0) {
	return -1;
    }

    /* TODO: verify that this is in fact a directory! */
    
    for (i=0; i < file_count; i++) {
	char tmp_file_name[PATH_SIZE];
	file_handle = 0;

        cur_extent.first = cur_extent.last = requested_file_handle;
        extent_array.extent_count = 1;
        extent_array.extent_array = &cur_extent;
	ret = trove_dspace_create(coll_id,
                                  &extent_array,
				  &file_handle,
				  TROVE_TEST_FILE,
				  NULL,
				  TROVE_FORCE_REQUESTED_HANDLE,
				  NULL,
                                  trove_context,
				  &op_id,
                                  NULL);
	while (ret == 0) ret = trove_dspace_test(
            coll_id, op_id, trove_context, &count, NULL, NULL, &state,
            TROVE_DEFAULT_TEST_TIMEOUT);
	if (ret < 0) {
	    fprintf(stderr, "dspace create failed.\n");
	    return -1;
	}

	s_attr.fs_id  = coll_id; /* for now */
	s_attr.handle = file_handle;
	s_attr.type   = TROVE_TEST_FILE; /* shouldn't need to fill this one in. */
	s_attr.uid    = myuid;
	s_attr.gid    = mygid;
	s_attr.mode   = 0755;
	s_attr.ctime  = mytime;
	count = 1;

	ret = trove_dspace_setattr(coll_id,
				   file_handle,
				   &s_attr,
				   0 /* flags */,
				   NULL /* user ptr */,
                                   trove_context,
				   &op_id,
                                   NULL);
	while (ret == 0) ret = trove_dspace_test(
            coll_id, op_id, trove_context, &count, NULL, NULL, &state,
            TROVE_DEFAULT_TEST_TIMEOUT);
	if (ret < 0) return -1;

	/* add new file name/handle pair to parent directory */
	snprintf(tmp_file_name, PATH_SIZE, "%s/file%d", path_name, i);
	key.buffer = tmp_file_name;
	key.buffer_sz = strlen(tmp_file_name) + 1;
	val.buffer = &file_handle;
	val.buffer_sz = sizeof(file_handle);

	ret = trove_keyval_write(coll_id, parent_handle, &key, &val,
                                 0, NULL, NULL, trove_context, &op_id, NULL);
	while (ret == 0) ret = trove_dspace_test(
            coll_id, op_id, trove_context, &count, NULL, NULL, &state,
            TROVE_DEFAULT_TEST_TIMEOUT);
	if (ret < 0) {
	    fprintf(stderr, "keyval write failed.\n");
	    return -1;
	}
    }
    
    trove_close_context(coll_id, trove_context);
    trove_finalize(TROVE_METHOD_DBPF);

    return 0;
}
Beispiel #10
0
int unionfs_ioctl_addbranch(struct inode *inode, unsigned int cmd,
			    unsigned long arg)
{
	int err;
	struct unionfs_addbranch_args *addargs = NULL;
	struct nameidata nd;
	char *path = NULL;
	int gen;
	int i;

	int pobjects;

	struct unionfs_usi_data *new_data = NULL;
	struct dentry **new_udi_dentry = NULL;
	struct inode **new_uii_inode = NULL;

	struct dentry *root = NULL;
	struct dentry *hidden_root = NULL;

	print_entry_location();

	err = -ENOMEM;
	addargs = KMALLOC(sizeof(struct unionfs_addbranch_args), GFP_KERNEL);
	if (!addargs)
		goto out;

	err = -EFAULT;
	if (copy_from_user
	    (addargs, (const void __user *)arg,
	     sizeof(struct unionfs_addbranch_args)))
		goto out;

	err = -EINVAL;
	if (addargs->ab_perms & ~(MAY_READ | MAY_WRITE | MAY_NFSRO))
		goto out;
	if (!(addargs->ab_perms & MAY_READ))
		goto out;

	err = -E2BIG;
	if (sbend(inode->i_sb) > FD_SETSIZE)
		goto out;

	err = -ENOMEM;
	if (!(path = getname((const char __user *)addargs->ab_path)))
		goto out;

	err = path_lookup(path, LOOKUP_FOLLOW, &nd);

	RECORD_PATH_LOOKUP(&nd);
	if (err)
		goto out;
	if ((err = check_branch(&nd))) {
		path_release(&nd);
		RECORD_PATH_RELEASE(&nd);
		goto out;
	}

	unionfs_write_lock(inode->i_sb);
	lock_dentry(inode->i_sb->s_root);

	root = inode->i_sb->s_root;
	for (i = dbstart(inode->i_sb->s_root); i <= dbend(inode->i_sb->s_root);
	     i++) {
		hidden_root = dtohd_index(root, i);
		if (is_branch_overlap(hidden_root, nd.dentry)) {
			err = -EINVAL;
			goto out;
		}
	}

	err = -EINVAL;
	if (addargs->ab_branch < 0
	    || (addargs->ab_branch > (sbend(inode->i_sb) + 1)))
		goto out;

	if ((err = newputmap(inode->i_sb)))
		goto out;

	stopd(inode->i_sb)->b_end++;
	dtopd(inode->i_sb->s_root)->udi_bcount++;
	set_dbend(inode->i_sb->s_root, dbend(inode->i_sb->s_root) + 1);
	itopd(inode->i_sb->s_root->d_inode)->b_end++;

	atomic_inc(&stopd(inode->i_sb)->usi_generation);
	gen = atomic_read(&stopd(inode->i_sb)->usi_generation);

	pobjects = sbend(inode->i_sb) + 1;

	/* Reallocate the dynamic structures. */
	new_data = alloc_new_data(pobjects);
	new_udi_dentry = alloc_new_dentries(pobjects);
	new_uii_inode = KZALLOC(sizeof(struct inode *) * pobjects, GFP_KERNEL);

	if (!new_udi_dentry || !new_uii_inode || !new_data) {
		err = -ENOMEM;
		goto out;
	}

	/* Copy the in-place values to our new structure. */
	for (i = 0; i < addargs->ab_branch; i++) {
		atomic_set(&(new_data[i].sbcount),
			   branch_count(inode->i_sb, i));

		new_data[i].branchperms = branchperms(inode->i_sb, i);
		new_data[i].hidden_mnt = stohiddenmnt_index(inode->i_sb, i);
		new_data[i].sb = stohs_index(inode->i_sb, i);

		new_udi_dentry[i] = dtohd_index(inode->i_sb->s_root, i);
		new_uii_inode[i] = itohi_index(inode->i_sb->s_root->d_inode, i);
	}

	/* Shift the ends to the right (only handle reallocated bits). */
	for (i = sbend(inode->i_sb) - 1; i >= (int)addargs->ab_branch; i--) {
		int j = i + 1;
		int pmindex;

		atomic_set(&new_data[j].sbcount, branch_count(inode->i_sb, i));

		new_data[j].branchperms = branchperms(inode->i_sb, i);
		new_data[j].hidden_mnt = stohiddenmnt_index(inode->i_sb, i);
		new_data[j].sb = stohs_index(inode->i_sb, i);
		new_udi_dentry[j] = dtohd_index(inode->i_sb->s_root, i);
		new_uii_inode[j] = itohi_index(inode->i_sb->s_root->d_inode, i);

		/* Update the newest putmap, so it is correct for later. */
		pmindex = stopd(inode->i_sb)->usi_lastputmap;
		pmindex -= stopd(inode->i_sb)->usi_firstputmap;
		stopd(inode->i_sb)->usi_putmaps[pmindex]->map[i] = j;

	}

	/* Now we can free the old ones. */
	KFREE(dtopd(inode->i_sb->s_root)->udi_dentry);
	KFREE(itopd(inode->i_sb->s_root->d_inode)->uii_inode);
	KFREE(stopd(inode->i_sb)->usi_data);

	/* Update the real pointers. */
	dtohd_ptr(inode->i_sb->s_root) = new_udi_dentry;
	itohi_ptr(inode->i_sb->s_root->d_inode) = new_uii_inode;
	stopd(inode->i_sb)->usi_data = new_data;

	/* Re-NULL the new ones so we don't try to free them. */
	new_data = NULL;
	new_udi_dentry = NULL;
	new_uii_inode = NULL;

	/* Put the new dentry information into it's slot. */
	set_dtohd_index(inode->i_sb->s_root, addargs->ab_branch, nd.dentry);
	set_itohi_index(inode->i_sb->s_root->d_inode, addargs->ab_branch,
			IGRAB(nd.dentry->d_inode));
	set_branchperms(inode->i_sb, addargs->ab_branch, addargs->ab_perms);
	set_branch_count(inode->i_sb, addargs->ab_branch, 0);
	set_stohiddenmnt_index(inode->i_sb, addargs->ab_branch, nd.mnt);
	set_stohs_index(inode->i_sb, addargs->ab_branch, nd.dentry->d_sb);

	atomic_set(&dtopd(inode->i_sb->s_root)->udi_generation, gen);
	atomic_set(&itopd(inode->i_sb->s_root->d_inode)->uii_generation, gen);

	fixputmaps(inode->i_sb);

      out:
	unlock_dentry(inode->i_sb->s_root);
	unionfs_write_unlock(inode->i_sb);

	KFREE(new_udi_dentry);
	KFREE(new_uii_inode);
	KFREE(new_data);
	KFREE(addargs);
	if (path)
		putname(path);

	print_exit_status(err);

	return err;
}
int main(
    int argc,
    char **argv)
{
    int ret = -1;
    int outcount = 0, count;
    struct BMI_unexpected_info request_info;
    flow_descriptor *flow_d = NULL;
    double time1, time2;
    int i;
    PINT_Request *req;
    char path_name[PATH_SIZE];
    TROVE_op_id op_id;
    TROVE_coll_id coll_id;
    TROVE_handle file_handle, parent_handle;
    TROVE_ds_state state;
    char *file_name;
    TROVE_keyval_s key, val;
    bmi_context_id context;
    TROVE_context_id trove_context;
    PVFS_handle_extent cur_extent;
    PVFS_handle_extent_array extent_array;

	/*************************************************************/
    /* initialization stuff */

    /* set debugging level */
    gossip_enable_stderr();
    gossip_set_debug_mask(
        0, (GOSSIP_FLOW_PROTO_DEBUG | GOSSIP_BMI_DEBUG_TCP));

    /* Init dists */
    PINT_dist_initialize(NULL);

    /* start up BMI */
    ret = BMI_initialize("bmi_tcp", "tcp://NULL:3335", BMI_INIT_SERVER);
    if (ret < 0)
    {
	fprintf(stderr, "BMI init failure.\n");
	return (-1);
    }

    ret = BMI_open_context(&context);
    if (ret < 0)
    {
	fprintf(stderr, "BMI_open_context() failure.\n");
	return (-1);
    }

    ret = trove_initialize(
        TROVE_METHOD_DBPF, NULL, storage_space, storage_space, 0);
    if (ret < 0)
    {
	fprintf(stderr, "initialize failed: run trove-mkfs first.\n");
	return -1;
    }

    /* initialize the flow interface */
    ret = PINT_flow_initialize("flowproto_multiqueue", 0);
    if (ret < 0)
    {
	fprintf(stderr, "flow init failure.\n");
	return (-1);
    }

    /* try to look up collection used to store file system */
    ret = trove_collection_lookup(
        TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id);
    if (ret < 0)
    {
	fprintf(stderr, "collection lookup failed.\n");
	return -1;
    }

    ret = trove_open_context(coll_id, &trove_context);
    if (ret < 0)
    {
	fprintf(stderr, "TROVE_open_context() failure.\n");
	return (-1);
    }

    /* find the parent directory name */
    strcpy(path_name, path_to_file);
    for (i = strlen(path_name); i >= 0; i--)
    {
	if (path_name[i] != '/')
	    path_name[i] = '\0';
	else
	    break;
    }
    file_name = path_to_file + strlen(path_name);
    printf("path is %s\n", path_name);
    printf("file is %s\n", file_name);

    /* find the parent directory handle */
    ret = path_lookup(coll_id, trove_context, path_name, &parent_handle);
    if (ret < 0)
    {
	return -1;
    }

    file_handle = 0;


    cur_extent.first = cur_extent.last = requested_file_handle;
    extent_array.extent_count = 1;
    extent_array.extent_array = &cur_extent;
    ret = trove_dspace_create(coll_id,
			      &extent_array,
			      &file_handle,
			      TROVE_TEST_FILE,
			      NULL, 
			      TROVE_FORCE_REQUESTED_HANDLE,
			      NULL, trove_context, &op_id, NULL);
    while (ret == 0)
	ret =
	    trove_dspace_test(coll_id, op_id, trove_context, &count, NULL, NULL,
			      &state, TROVE_DEFAULT_TEST_TIMEOUT);
    if (ret < 0)
    {
	fprintf(stderr, "dspace create failed.\n");
	return -1;
    }

    /* TODO: set attributes of file? */

    /* add new file name/handle pair to parent directory */
    key.buffer = file_name;
    key.buffer_sz = strlen(file_name) + 1;
    val.buffer = &file_handle;
    val.buffer_sz = sizeof(file_handle);
    ret =
	trove_keyval_write(coll_id, parent_handle, &key, &val, 0, NULL, NULL,
			   trove_context, &op_id, NULL);
    while (ret == 0)
	ret =
	    trove_dspace_test(coll_id, op_id, trove_context, &count, NULL, NULL,
			      &state, TROVE_DEFAULT_TEST_TIMEOUT);
    if (ret < 0)
    {
	fprintf(stderr, "keyval write failed.\n");
	return -1;
    }


    /* wait for an initial communication via BMI */
    /* we don't give a crap about that message except that it tells us
     * where to find the client 
     */
    do
    {
	ret = BMI_testunexpected(1, &outcount, &request_info, 10);
    } while (ret == 0 && outcount == 0);
    if (ret < 0 || request_info.error_code != 0)
    {
	fprintf(stderr, "waitunexpected failure.\n");
	return (-1);
    }
    BMI_unexpected_free(request_info.addr, request_info.buffer);

	/******************************************************/
    /* setup request/dist stuff */

    /* request description */
    /* just want one contiguous region */
    ret = PVFS_Request_contiguous(TEST_SIZE, PVFS_BYTE, &req);
    if (ret < 0)
    {
	fprintf(stderr, "PVFS_Request_contiguous() failure.\n");
	return (-1);
    }


	/******************************************************/
    /* setup communicaton stuff */

    /* create a flow descriptor */
    flow_d = PINT_flow_alloc();
    if (!flow_d)
    {
	fprintf(stderr, "flow_alloc failed.\n");
	return (-1);
    }

    /* file data */
    flow_d->file_data.fsize = TEST_SIZE;
    flow_d->file_data.server_nr = 0;
    flow_d->file_data.server_ct = 1;
    flow_d->file_data.extend_flag = 1;
    flow_d->file_data.dist = PINT_dist_create("basic_dist");
    if (!flow_d->file_data.dist)
    {
	fprintf(stderr, "Error: failed to create dist.\n");
	return (-1);
    }
    ret = PINT_dist_lookup(flow_d->file_data.dist);
    if (ret != 0)
    {
	fprintf(stderr, "Error: failed to lookup dist.\n");
	return (-1);
    }
    flow_d->file_req = req;
    flow_d->tag = 0;
    flow_d->user_ptr = NULL;
    flow_d->aggregate_size = TEST_SIZE;

    /* fill in flow details */
    flow_d->src.endpoint_id = BMI_ENDPOINT;
    flow_d->src.u.bmi.address = request_info.addr;
    flow_d->dest.endpoint_id = TROVE_ENDPOINT;
    flow_d->dest.u.trove.handle = file_handle;
    flow_d->dest.u.trove.coll_id = coll_id;

	/***************************************************
	 * test bmi to file (analogous to a client side write)
	 */

    time1 = Wtime();
    ret = block_on_flow(flow_d);
    if (ret < 0)
    {
	return (-1);
    }
    time2 = Wtime();

#if 0
    printf("Server bw (recv): %f MB/sec\n",
	   ((TEST_SIZE) / ((time2 - time1) * 1000000.0)));
#endif

	/*******************************************************/
    /* final cleanup and output */

    PINT_flow_free(flow_d);

    /* shut down flow interface */
    ret = PINT_flow_finalize();
    if (ret < 0)
    {
	fprintf(stderr, "flow finalize failure.\n");
	return (-1);
    }

    /* shut down BMI */
    BMI_close_context(context);
    BMI_finalize();

    trove_close_context(coll_id, trove_context);
    trove_finalize(TROVE_METHOD_DBPF);

    gossip_disable();
    return (0);
}
Beispiel #12
0
int main(int argc, char **argv)
{
    int ret, count, i, fd;
    TROVE_op_id op_id;
    TROVE_coll_id coll_id;
    TROVE_handle file_handle, parent_handle;
    TROVE_ds_state state;
    TROVE_keyval_s key, val;
    TROVE_ds_attributes_s s_attr;
    TROVE_size f_size;
    char *file_name;
    char path_name[PATH_SIZE];
    char *buf;
    TROVE_context_id trove_context = -1;

    ret = parse_args(argc, argv);
    if (ret < 0) {
	fprintf(stderr, "argument parsing failed.\n");
	return -1;
    }

    if (optind + 1 >= argc) return -1;

    strcpy(path_to_file, argv[optind]);
    strcpy(path_to_unix, argv[optind+1]);

    ret = trove_initialize(
        TROVE_METHOD_DBPF, NULL, storage_space, 0);
    if (ret < 0) {
	fprintf(stderr, "initialize failed.\n");
	return -1;
    }

    /* try to look up collection used to store file system */
    ret = trove_collection_lookup(
        TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id);
    if (ret < 0) {
	fprintf(stderr, "collection lookup failed.\n");
	return -1;
    }

    ret = trove_open_context(coll_id, &trove_context);
    if (ret < 0)
    {
        fprintf(stderr, "trove_open_context failed\n");
        return -1;
    }

    /* find the parent directory name */
    strcpy(path_name, path_to_file);
    for (i=strlen(path_name); i >= 0; i--) {
	if (path_name[i] != '/') path_name[i] = '\0';
	else break;
    }
    file_name = path_to_file + strlen(path_name);
#if 0
    printf("path is %s\n", path_name);
    printf("file is %s\n", file_name);
#endif

    /* find the parent directory handle */
    ret = path_lookup(coll_id, path_name, &parent_handle);
    if (ret < 0) {
	return -1;
    }


    /* add new file name/handle pair to parent directory */
    key.buffer = file_name;
    key.buffer_sz = strlen(file_name) + 1;
    val.buffer = &file_handle;
    val.buffer_sz = sizeof(file_handle);

    ret = trove_keyval_read(coll_id, parent_handle, &key, &val,
                            0, NULL, NULL, trove_context, &op_id, NULL);
    count = 1;
    while (ret == 0) ret = trove_dspace_test(
        coll_id, op_id, trove_context, &count, NULL, NULL, &state,
        TROVE_DEFAULT_TEST_TIMEOUT);
    if (ret < 0) {
	fprintf(stderr, "keyval read failed.\n");
	return -1;
    }

    ret = trove_dspace_getattr(coll_id,
			       file_handle,
			       &s_attr,
			       0 /* flags */,
			       NULL,
                               trove_context,
			       &op_id,
                               NULL);
    while (ret == 0) ret = trove_dspace_test(
        coll_id, op_id, trove_context, &count, NULL, NULL, &state,
        TROVE_DEFAULT_TEST_TIMEOUT);
    if (ret < 0) return -1;

    /* get a buffer */
    buf = (char *) malloc((size_t) s_attr.u.datafile.b_size);
    if (buf == NULL) return -1;

    f_size = s_attr.u.datafile.b_size;
    /* read data from trove file */
    ret = trove_bstream_read_at(coll_id,
				file_handle,
				buf,
				&f_size,
				0, /* offset */
				0, /* flags */
				NULL, /* vtag */
				NULL, /* user ptr */
                                trove_context,
				&op_id,
                                NULL);
    count = 1;
    while ( ret == 0) ret = trove_dspace_test(
        coll_id, op_id, trove_context, &count, NULL, NULL, &state,
        TROVE_DEFAULT_TEST_TIMEOUT);
    if (ret < 0 ) {
	fprintf(stderr, "bstream write failed.\n");
	return -1;
    }

    /* open up the unix file */
    fd = open(path_to_unix, O_RDWR | O_CREAT, 0644);
    if (fd < 0) {
	perror("open");
	return -1;
    }

    /* write data to file */
    write(fd, buf, f_size);

    close(fd);

    trove_close_context(coll_id, trove_context);
    trove_finalize(TROVE_METHOD_DBPF);
#if 0
    printf("created file %s (handle = %d)\n", file_name, (int) file_handle);
#endif
    return 0;
}
Beispiel #13
0
static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info
			     *hidden_root_info, char *options)
{
	struct nameidata nd;
	char *name;
	int err = 0;
	int branches = 1;
	int bindex = 0;
	int i = 0;
	int j = 0;

	struct dentry *dent1 = NULL;
	struct dentry *dent2 = NULL;

	if (options[0] == '\0') {
		printk(KERN_WARNING "unionfs: no branches specified\n");
		err = -EINVAL;
		goto out;
	}

	/* Each colon means we have a separator, this is really just a rough
	 * guess, since strsep will handle empty fields for us. */
	for (i = 0; options[i]; i++) {
		if (options[i] == ':')
			branches++;
	}

	/* allocate space for underlying pointers to hidden dentry */
	if (!(stopd(sb)->usi_data = alloc_new_data(branches))) {
		err = -ENOMEM;
		goto out;
	}

	if (!(hidden_root_info->udi_dentry = alloc_new_dentries(branches))) {
		err = -ENOMEM;
		goto out;
	}

	/* now parsing the string b1:b2=rw:b3=ro:b4 */
	branches = 0;
	while ((name = strsep(&options, ":")) != NULL) {
		int perms;

		if (!*name)
			continue;

		branches++;

		/* strip off =rw or =ro if it is specified. */
		perms = parse_branch_mode(name);
		if (!bindex && !(perms & MAY_WRITE)) {
			err = -EINVAL;
			goto out;
		}

		fist_dprint(4, "unionfs: using directory: %s (%c%c%c)\n",
			    name, perms & MAY_READ ? 'r' : '-',
			    perms & MAY_WRITE ? 'w' : '-',
			    perms & MAY_NFSRO ? 'n' : '-');

		err = path_lookup(name, LOOKUP_FOLLOW, &nd);
		RECORD_PATH_LOOKUP(&nd);
		if (err) {
			printk(KERN_WARNING "unionfs: error accessing "
			       "hidden directory '%s' (error %d)\n", name, err);
			goto out;
		}

		if ((err = check_branch(&nd))) {
			printk(KERN_WARNING "unionfs: hidden directory "
			       "'%s' is not a valid branch\n", name);
			path_release(&nd);
			RECORD_PATH_RELEASE(&nd);
			goto out;
		}

		hidden_root_info->udi_dentry[bindex] = nd.dentry;

		set_stohiddenmnt_index(sb, bindex, nd.mnt);
		set_branchperms(sb, bindex, perms);
		set_branch_count(sb, bindex, 0);

		if (hidden_root_info->udi_bstart < 0)
			hidden_root_info->udi_bstart = bindex;
		hidden_root_info->udi_bend = bindex;
		bindex++;
	}

	if (branches == 0) {
		printk(KERN_WARNING "unionfs: no branches specified\n");
		err = -EINVAL;
		goto out;
	}

	BUG_ON(branches != (hidden_root_info->udi_bend + 1));

	/* ensure that no overlaps exist in the branches */
	for (i = 0; i < branches; i++) {
		for (j = i + 1; j < branches; j++) {
			dent1 = hidden_root_info->udi_dentry[i];
			dent2 = hidden_root_info->udi_dentry[j];

			if (is_branch_overlap(dent1, dent2)) {
				goto out_overlap;
			}
		}
	}

      out_overlap:

	if (i != branches) {
		printk(KERN_WARNING "unionfs: branches %d and %d overlap\n", i,
		       j);
		err = -EINVAL;
		goto out;
	}

      out:
	if (err) {
		for (i = 0; i < branches; i++) {
			if (hidden_root_info->udi_dentry[i])
				DPUT(hidden_root_info->udi_dentry[i]);
		}

		KFREE(hidden_root_info->udi_dentry);
		KFREE(stopd(sb)->usi_data);

		/* MUST clear the pointers to prevent potential double free if
		 * the caller dies later on
		 */
		hidden_root_info->udi_dentry = NULL;
		stopd(sb)->usi_data = NULL;
	}
	return err;
}
Beispiel #14
0
static struct dentry *lofs_mount(
    struct file_system_type *fs_type,
    int flags,
    const char *dev_name,
    void *raw_data)
{
    static const struct qstr slash = { .name = "/", .len = 1 };
    struct super_block *s;
    struct lofs_sb_info *sbi;
    struct lofs_dentry_info *root_info;
    struct inode *inode;
    const char *err = "Getting sb failed";
    struct path path;
    int rc;

    sbi = kmem_cache_zalloc(lofs_sb_info_cache, GFP_KERNEL);
    if (!sbi) {
        rc = -ENOMEM;
        goto out;
    }

    s = sget(fs_type, NULL, set_anon_super, NULL);
    if (IS_ERR(s)) {
        rc = PTR_ERR(s);
        goto out;
    }

    s->s_flags = flags;
#if defined(HAVE_BACKING_DEV)
    rc = bdi_setup_and_register(&sbi->bdi, "lofs", BDI_CAP_MAP_COPY);
    if (rc)
        goto out1;

    s->s_bdi = &sbi->bdi;
#endif
    lofs_set_superblock_private(s, sbi);

    /* ->kill_sb() will take care of sbi after that point */
    sbi = NULL;
    s->s_op   = &lofs_sops;
    s->s_d_op = &lofs_dops;

    err = "Reading sb failed";
    rc = kern_path(slash.name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
    if (rc) {
        lofs_printk(KERN_WARNING, "kern_path() failed\n");
        goto out1;
    }

    lofs_set_superblock_lower(s, path.dentry->d_sb);
    s->s_maxbytes = path.dentry->d_sb->s_maxbytes;
    s->s_blocksize = path.dentry->d_sb->s_blocksize;
    s->s_magic = 0x10f5;

    inode = lofs_get_inode(path.dentry->d_inode, s);
    rc = PTR_ERR(inode);
    if (IS_ERR(inode)) {
        goto out_free;
    }

#ifdef HAVE_D_MAKE_ROOT
    s->s_root = d_make_root(inode);
#else
    s->s_root = d_alloc_root(inode);
    if (!s->s_root) {
        iput(inode);
    }
#endif
    if (!s->s_root) {
        rc = -ENOMEM;
        goto out_free;
    }

    rc = -ENOMEM;
    root_info = kmem_cache_zalloc(lofs_dentry_info_cache, GFP_KERNEL);
    if (!root_info)
        goto out_free;

    /* ->kill_sb() will take care of root_info */
    lofs_set_dentry_private(s->s_root, root_info);
    lofs_set_dentry_lower(s->s_root, path.dentry);
    lofs_set_dentry_lower_mnt(s->s_root, path.mnt);

    s->s_flags |= MS_ACTIVE;
    return dget(s->s_root);

out_free:
    path_put(&path);
out1:
    deactivate_locked_super(s);
out:
    if (sbi) {
        kmem_cache_free(lofs_sb_info_cache, sbi);
    }
    printk(KERN_ERR "%s; rc = [%d]\n", err, rc);
    return ERR_PTR(rc);
}

/**
 * lofs_kill_block_super
 * @sb: The lofs super block
 *
 * Used to bring the superblock down and free the private data.
 */
static void lofs_kill_block_super(struct super_block *sb)
{
    struct lofs_sb_info *sb_info = lofs_superblock_to_private(sb);
    kill_anon_super(sb);
#if defined(HAVE_BACKING_DEV)
    if (sb_info) {
        bdi_destroy(&sb_info->bdi);
    }
#endif
    kmem_cache_free(lofs_sb_info_cache, sb_info);
}

#else /* !HAVE_MOUNT_IN_FS_TYPE */

/**
 * lofs_fill_super
 * @sb: The lofs super block
 * @raw_data: The options passed to mount
 * @silent: Not used but required by function prototype
 *
 * Sets up what we can of the sb, rest is done in lofs_read_super
 *
 * Returns zero on success; non-zero otherwise
 */
static int
lofs_fill_super(struct super_block *sb, void *raw_data, int silent)
{
    int rc = 0;
    struct inode *inode;
    struct nameidata nd;

    /* Released in lofs_put_super() */
    struct lofs_sb_info *sbi;
    sbi = kmem_cache_zalloc(lofs_sb_info_cache, GFP_KERNEL);
    if (!sbi) {
        lofs_printk(KERN_WARNING, "Out of memory\n");
        return -ENOMEM;
    }
    lofs_set_superblock_private(sb, sbi);
    sb->s_op = (struct super_operations *) &lofs_sops;

    /* Released through deactivate_super(sb) from get_sb_nodev */
#if defined(HAVE_S_D_OP)
    sb->s_d_op = &lofs_dops;
#endif

    rc = path_lookup("/", LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd);
    if (rc) {
        lofs_printk(KERN_WARNING, "path_lookup() failed\n");
        return rc;
    }
    lofs_set_superblock_lower(sb, NAMEIDATA_TO_DENTRY(&nd)->d_sb);
    sb->s_maxbytes =  NAMEIDATA_TO_DENTRY(&nd)->d_sb->s_maxbytes;
    sb->s_blocksize = NAMEIDATA_TO_DENTRY(&nd)->d_sb->s_blocksize;
#ifdef HAVE_ADDRESS_SPACE_OPS_EXT
    sb->s_flags |= MS_HAS_NEW_AOPS;
#endif

    /* Get the root inode and dentry.  We have to bootstrap this one,
     * since it doesn't get created via the regular lookup mechanism.
     */

    inode = lofs_get_inode(NAMEIDATA_TO_DENTRY(&nd)->d_inode, sb);
    if (IS_ERR(inode)) {
        dput(NAMEIDATA_TO_DENTRY(&nd));
        mntput(NAMEIDATA_TO_VFSMNT(&nd));
        return PTR_ERR(inode);
    }

    sb->s_root = d_alloc_root(inode);
    if (!sb->s_root) {
        iput(inode);
        dput(NAMEIDATA_TO_DENTRY(&nd));
        mntput(NAMEIDATA_TO_VFSMNT(&nd));
        return -ENOMEM;
    }
    lofs_set_dentry_private(sb->s_root,
            kmem_cache_zalloc(lofs_dentry_info_cache, GFP_KERNEL));
    lofs_set_dentry_lower(sb->s_root, NAMEIDATA_TO_DENTRY(&nd));
    lofs_set_dentry_lower_mnt(sb->s_root, NAMEIDATA_TO_VFSMNT(&nd));

#if !defined(HAVE_S_D_OP)
    sb->s_root->d_op = (struct dentry_operations *) &lofs_dops;
#endif

    return 0;
}
Beispiel #15
0
int main(int argc, char **argv)
{
    int ret, count, i;
    char *file_name;
    char path_name[PATH_SIZE];

    TROVE_op_id op_id;
    TROVE_coll_id coll_id;
    TROVE_handle file_handle, parent_handle;
    TROVE_ds_state state;
    TROVE_keyval_s key, val;
    TROVE_ds_attributes_s s_attr;
    TROVE_context_id trove_context = -1;

    ret = parse_args(argc, argv);
    if (ret < 0) {
	fprintf(stderr, "argument parsing failed.\n");
	return -1;
    }

    ret = trove_initialize(
        TROVE_METHOD_DBPF, NULL, storage_space, storage_space, 0);
    if (ret < 0) {
	fprintf(stderr, "initialize failed.\n");
	return -1;
    }

    /* try to look up collection used to store file system */
    ret = trove_collection_lookup(
        TROVE_METHOD_DBPF, file_system, &coll_id, NULL, &op_id);
    if (ret < 0) {
	fprintf(stderr, "collection lookup failed.\n");
	return -1;
    }

    ret = trove_open_context(coll_id, &trove_context);
    if (ret < 0)
    {
        fprintf(stderr, "trove_open_context failed\n");
        return -1;
    }

    /* find the parent directory name */
    strcpy(path_name, path_to_file);
    for (i=strlen(path_name); i >= 0; i--) {
	if (path_name[i] != '/') path_name[i] = '\0';
	else break;
    }
    file_name = path_to_file + strlen(path_name);
#if 0
    printf("path is %s\n", path_name);
    printf("file is %s\n", file_name);
#endif

    /* find the parent directory handle */
    ret = path_lookup(coll_id, path_name, &parent_handle);
    if (ret < 0) {
	return -1;
    }

    /* TODO: make a is_dir function... maybe make a full blown stat(2)? */
    
    /* look up the handle for the file */
    memset(&key, 0, sizeof(key));
    memset(&val, 0, sizeof(val));
    key.buffer = file_name;
    key.buffer_sz = strlen(file_name)+1;
    val.buffer = &file_handle;
    val.buffer_sz = sizeof(TROVE_handle);

    /* it would be smart to verify that this is a directory first... */
    ret = trove_keyval_read(coll_id, parent_handle, &key, &val,
                            0, NULL, NULL, trove_context, &op_id, NULL);
    while (ret == 0) ret = trove_dspace_test(
        coll_id, op_id, trove_context, &count, NULL, NULL, &state,
        TROVE_DEFAULT_TEST_TIMEOUT);
    if ( ret < 0 || state == -1) {
	    fprintf(stderr, "read failed for key %s\n", file_name);
	    return -1;
    }

    ret = trove_dspace_getattr(coll_id,
			       file_handle,
			       &s_attr,
			       0 /* flags */,
			       NULL,
                               trove_context,
			       &op_id,
                               NULL);
    while (ret == 0) ret = trove_dspace_test(
        coll_id, op_id, trove_context, &count, NULL, NULL, &state,
        TROVE_DEFAULT_TEST_TIMEOUT);
    if (ret < 0) return -1;

    /* 'handles are everything':  now that we've gotten a handle from the
     * file_name, we can wipe the keyval (via name) and the dspace (via
     * handle)*/

    key.buffer = file_name;
    key.buffer_sz = strlen(file_name)+1;

    ret = trove_keyval_remove(coll_id, parent_handle, &key, NULL,
                              0, NULL, NULL, trove_context, &op_id, NULL);
    while (ret == 0) ret = trove_dspace_test(
        coll_id, op_id, trove_context, &count, NULL, NULL, &state,
        TROVE_DEFAULT_TEST_TIMEOUT);
    if (ret < 0 ) {
	    fprintf(stderr, "removal failed for %s\n", file_name);
	    return -1;
    }

    /* the question: is it up to the caller to clean up the dspace if it removed the last entry?  no no no*/
    /* gar gar being dense:  the dspace gets removed.  */
    ret = trove_dspace_remove(coll_id, 
			      file_handle,
			      TROVE_SYNC,
			      NULL,
                              trove_context,
			      &op_id,
                              NULL);
    while (ret == 0) ret = trove_dspace_test(
        coll_id, op_id, trove_context, &count, NULL, NULL, &state,
        TROVE_DEFAULT_TEST_TIMEOUT);
    if (ret < 0) {
	fprintf(stderr, "dspace remove failed.\n");
	return -1;
    }

    trove_close_context(coll_id, trove_context);
    trove_finalize(TROVE_METHOD_DBPF);
    printf("file %s removed (file handle = %d, parent handle = %d).\n",
	   file_name, 
	   (int) file_handle,
	   (int) parent_handle);

    return 0;
}