/* allocate new dentry private data */
int new_dentry_private_data(struct dentry *dentry)
{
	struct wrapfs_dentry_info *info = WRAPFS_D(dentry);

	/* use zalloc to init dentry_info.lower_path */
	info = kmem_cache_zalloc(wrapfs_dentry_cachep, GFP_ATOMIC);
	if (!info)
		return -ENOMEM;

	spin_lock_init(&info->lock);
	dentry->d_fsdata = info;

	return 0;
}
Exemple #2
0
static void wrapfs_d_release(struct dentry *dentry)
{
	if (!dentry)
		goto out;
	if (unlikely(!WRAPFS_D(dentry)))
		goto out;
	UDBG;
/*	wrapfs_lock_dentry(dentry, WRAPFS_DMUTEX_CHILD);
	path_put_lowers_all(dentry, true); */
	UDBG;
	/* release and reset the lower paths */
/*	wrapfs_put_reset_lower_path(dentry);
	wrpafs_unlock_dentry(dentry);
*/
out:
	free_dentry_private_data(dentry);
	return;
}
/*
 * There is no need to lock the wrapfs_super_info's rwsem as there is no
 * way anyone can have a reference to the superblock at this point in time.
 */
static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent)
{
	int err = 0, i = 0;
	struct wrapfs_dentry_info *lower_root_info = NULL;
	struct inode *inode = NULL;
	if (!raw_data) {
		printk(KERN_ERR
			"u2fs: read_super: missing data argument\n");
		err = -EINVAL;
		goto out;
	}

	/* allocate superblock private data */

	sb->s_fs_info = kzalloc(sizeof(struct wrapfs_sb_info), GFP_KERNEL);
	if (!WRAPFS_SB(sb)) {
		printk(KERN_CRIT "u2fs: read_super: out of memory\n");
		err = -ENOMEM;
		goto out_free;
	}

	atomic_set(&WRAPFS_SB(sb)->generation, 1);
	WRAPFS_SB(sb)->high_branch_id = -1;
/*      Parsing the Inputs      */
	lower_root_info = wrapfs_parse_options(sb, raw_data);
	if (IS_ERR(lower_root_info)) {
		printk(KERN_ERR
			"u2fs: read_super: error while parsing options"
			"(err = %ld)\n", PTR_ERR(lower_root_info));

		err = PTR_ERR(lower_root_info);
		lower_root_info = NULL;
		goto out_free;
	}

	/* set the lower superblock field of upper superblock */
	for (i = 0; i <= 1; i++) {
		struct dentry *d = lower_root_info->lower_paths[i].dentry;
		atomic_inc(&d->d_sb->s_active);
		wrapfs_set_lower_super_idx(sb, i, d->d_sb);
	}

	/* inherit maxbytes from highest priority branch */
	sb->s_maxbytes = wrapfs_lower_super_idx(sb, 0)->s_maxbytes;

	/*
	* Our c/m/atime granularity is 1 ns because we may stack on file
	* systems whose granularity is as good.
	*/
	sb->s_time_gran = 1;
	sb->s_op = &wrapfs_sops;

	/* get a new inode and allocate our root dentry */

	inode = wrapfs_new_iget(sb, iunique(sb, 1));
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		goto out_sput;
	}

	sb->s_root = d_alloc_root(inode);
	if (unlikely(!sb->s_root)) {
		err = -ENOMEM;
		goto out_iput;
	}

	d_set_d_op(sb->s_root, &wrapfs_dops);

	/* link the upper and lower dentries */
	sb->s_root->d_fsdata = NULL;
	err = new_dentry_private_data(sb->s_root);
	if (unlikely(err))
		goto out_freeroot;

	/* if get here: cannot have error */
	/* set the lower dentries for s_root */

	for (i = 0; i <= 1 ; i++) {
		struct dentry *d;
		struct vfsmount *m;
		d = lower_root_info->lower_paths[i].dentry;
		m = lower_root_info->lower_paths[i].mnt;
		wrapfs_set_lower_dentry_idx(sb->s_root, i, d);
		wrapfs_set_lower_mnt_idx(sb->s_root, i, m);
	}
	atomic_set(&WRAPFS_D(sb->s_root)->generation, 1);
	if (atomic_read(&inode->i_count) <= 1)
		wrapfs_fill_inode(sb->s_root, inode);
	/*
	* No need to call interpose because we already have a positive
	* dentry, which was instantiated by d_alloc_root.  Just need to
	* d_rehash it.
	*/
	d_rehash(sb->s_root);
	if (!silent)
		printk(KERN_INFO
			"u2fs: mounted on top of type\n");
	goto out;

	/* all is well */
	/* no longer needed: free_dentry_private_data(sb->s_root); */
out_freeroot:
	if (WRAPFS_D(sb->s_root)) {
		kfree(WRAPFS_D(sb->s_root)->lower_paths);
		free_dentry_private_data(sb->s_root);
	}
	dput(sb->s_root);
out_iput:
	iput(inode);
out_sput:
	/* drop refs we took earlier */
	if (lower_root_info && !IS_ERR(lower_root_info)) {
		for (i = 0; i <= 1; i++) {
			struct dentry *d;
			d = lower_root_info->lower_paths[i].dentry;
			atomic_dec(&d->d_sb->s_active);
			path_put(&lower_root_info->lower_paths[i]);
		}
		kfree(lower_root_info->lower_paths);
		kfree(lower_root_info);
		lower_root_info = NULL;
	}
out_free:
	kfree(WRAPFS_SB(sb)->data);
	kfree(WRAPFS_SB(sb));
	sb->s_fs_info = NULL;
out:
	if (lower_root_info && !IS_ERR(lower_root_info)) {
		kfree(lower_root_info->lower_paths);
		kfree(lower_root_info);
	}
	return err;
}