Ejemplo n.º 1
0
/*
 * copy-down the file and unlink the bsrc file.
 * - unlink the bdst whout if exist
 * - copy-down the file (with whtmp name and rename)
 * - unlink the bsrc file
 */
static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a)
{
	int err;

	err = au_do_mkdir(dmsg, a);
	if (!err)
		err = au_do_lock(dmsg, a);
	if (unlikely(err))
		goto out;

	/*
	 * do not revert the activities we made on bdst since they should be
	 * harmless in aufs.
	 */

	err = au_do_cpdown(dmsg, a);
	if (!err)
		err = au_do_unlink_wh(dmsg, a);
	if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER))
		err = au_do_unlink(dmsg, a);
	if (unlikely(err))
		goto out_unlock;

	AuDbg("%pd2, 0x%x, %d --> %d\n",
	      a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst);
	if (find_lower_writable(a) < 0)
		a->mvdown.flags |= AUFS_MVDOWN_BOTTOM;

	if (a->mvdown.flags & AUFS_MVDOWN_STFS)
		au_do_stfs(dmsg, a);

	/* maintain internal array */
	if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) {
		au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL);
		au_set_dbtop(a->dentry, a->mvd_bdst);
		au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0);
		au_set_ibtop(a->inode, a->mvd_bdst);
	} else {
		/* hide the lower */
		au_set_h_dptr(a->dentry, a->mvd_bdst, NULL);
		au_set_dbbot(a->dentry, a->mvd_bsrc);
		au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0);
		au_set_ibbot(a->inode, a->mvd_bsrc);
	}
	if (au_dbbot(a->dentry) < a->mvd_bdst)
		au_set_dbbot(a->dentry, a->mvd_bdst);
	if (au_ibbot(a->inode) < a->mvd_bdst)
		au_set_ibbot(a->inode, a->mvd_bdst);

out_unlock:
	au_do_unlock(dmsg, a);
out:
	AuTraceErr(err);
	return err;
}
Ejemplo n.º 2
0
static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a)
{
    int err;
    struct au_branch *br;

    err = -EISDIR;
    if (unlikely(S_ISDIR(a->inode->i_mode)))
        goto out;

    err = -EINVAL;
    if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER))
        a->mvd_bsrc = au_ibstart(a->inode);
    else {
        a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid);
        if (unlikely(a->mvd_bsrc < 0
                     || (a->mvd_bsrc < au_dbstart(a->dentry)
                         || au_dbend(a->dentry) < a->mvd_bsrc
                         || !au_h_dptr(a->dentry, a->mvd_bsrc))
                     || (a->mvd_bsrc < au_ibstart(a->inode)
                         || au_ibend(a->inode) < a->mvd_bsrc
                         || !au_h_iptr(a->inode, a->mvd_bsrc)))) {
            a->mvd_errno = EAU_MVDOWN_NOUPPER;
            AU_MVD_PR(dmsg, "no upper\n");
            goto out;
        }
    }
    if (unlikely(a->mvd_bsrc == au_sbend(a->sb))) {
        a->mvd_errno = EAU_MVDOWN_BOTTOM;
        AU_MVD_PR(dmsg, "on the bottom\n");
        goto out;
    }
    a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc);
    br = au_sbr(a->sb, a->mvd_bsrc);
    err = au_br_rdonly(br);
    if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) {
        if (unlikely(err))
            goto out;
    } else if (!(vfsub_native_ro(a->mvd_h_src_inode)
                 || IS_APPEND(a->mvd_h_src_inode))) {
        if (err)
            a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R;
        /* go on */
    } else
        goto out;

    err = -EINVAL;
    if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) {
        a->mvd_bdst = find_lower_writable(a);
        if (unlikely(a->mvd_bdst < 0)) {
            a->mvd_errno = EAU_MVDOWN_BOTTOM;
            AU_MVD_PR(dmsg, "no writable lower branch\n");
            goto out;
        }
    } else {
        a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid);
        if (unlikely(a->mvd_bdst < 0
                     || au_sbend(a->sb) < a->mvd_bdst)) {
            a->mvd_errno = EAU_MVDOWN_NOLOWERBR;
            AU_MVD_PR(dmsg, "no lower brid\n");
            goto out;
        }
    }

    err = au_mvd_args_busy(dmsg, a);
    if (!err)
        err = au_mvd_args_parent(dmsg, a);
    if (!err)
        err = au_mvd_args_intermediate(dmsg, a);
    if (!err)
        err = au_mvd_args_exist(dmsg, a);
    if (!err)
        AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst);

out:
    AuTraceErr(err);
    return err;
}