static void au_ren_refresh(struct au_ren_args *a)
{
	aufs_bindex_t bend, bindex;
	struct dentry *d, *h_d;
	struct inode *i, *h_i;
	struct super_block *sb;

	d = a->dst_dentry;
	d_drop(d);
	if (a->h_dst)
		/* already dget-ed by au_ren_or_cpup() */
		au_set_h_dptr(d, a->btgt, a->h_dst);

	i = a->dst_inode;
	if (i) {
		if (!au_ftest_ren(a->flags, ISDIR))
			vfsub_drop_nlink(i);
		else {
			vfsub_dead_dir(i);
			au_cpup_attr_timesizes(i);
		}
		au_update_dbrange(d, /*do_put_zero*/1);
	} else {
		bend = a->btgt;
		for (bindex = au_dbstart(d); bindex < bend; bindex++)
			au_set_h_dptr(d, bindex, NULL);
		bend = au_dbend(d);
		for (bindex = a->btgt + 1; bindex <= bend; bindex++)
			au_set_h_dptr(d, bindex, NULL);
		au_update_dbrange(d, /*do_put_zero*/0);
	}

	d = a->src_dentry;
	au_set_dbwh(d, -1);
	bend = au_dbend(d);
	for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
		h_d = au_h_dptr(d, bindex);
		if (h_d)
			au_set_h_dptr(d, bindex, NULL);
	}
	au_set_dbend(d, a->btgt);

	sb = d->d_sb;
	i = a->src_inode;
	if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
		return; /* success */

	bend = au_ibend(i);
	for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
		h_i = au_h_iptr(i, bindex);
		if (h_i) {
			au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
			/* ignore this error */
			au_set_h_iptr(i, bindex, NULL, 0);
		}
	}
	au_set_ibend(i, a->btgt);
}
Exemplo n.º 2
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_dbstart(a->dentry, a->mvd_bdst);
        au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0);
        au_set_ibstart(a->inode, a->mvd_bdst);
    }
    if (au_dbend(a->dentry) < a->mvd_bdst)
        au_set_dbend(a->dentry, a->mvd_bdst);
    if (au_ibend(a->inode) < a->mvd_bdst)
        au_set_ibend(a->inode, a->mvd_bdst);

out_unlock:
    au_do_unlock(dmsg, a);
out:
    AuTraceErr(err);
    return err;
}
Exemplo n.º 3
0
static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
			 struct dentry *h_parent, void *arg)
{
	int err, rerr;
	aufs_bindex_t bopq, bstart;
	struct path h_path;
	struct dentry *parent;
	struct inode *h_dir, *h_inode, *inode, *dir;
	struct au_cpdown_dir_args *args = arg;

	bstart = au_dbstart(dentry);
	/* dentry is di-locked */
	parent = dget_parent(dentry);
	dir = parent->d_inode;
	h_dir = h_parent->d_inode;
	AuDebugOn(h_dir != au_h_iptr(dir, bdst));
	IMustLock(h_dir);

	err = au_lkup_neg(dentry, bdst);
	if (unlikely(err < 0))
		goto out;
	h_path.dentry = au_h_dptr(dentry, bdst);
	h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
	err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
			      S_IRWXU | S_IRUGO | S_IXUGO);
	if (unlikely(err))
		goto out_put;
	au_fset_cpdown(args->flags, MADE_DIR);

	bopq = au_dbdiropq(dentry);
	au_fclr_cpdown(args->flags, WHED);
	au_fclr_cpdown(args->flags, DIROPQ);
	if (au_dbwh(dentry) == bdst)
		au_fset_cpdown(args->flags, WHED);
	if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
		au_fset_cpdown(args->flags, PARENT_OPQ);
	h_inode = h_path.dentry->d_inode;
	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
	if (au_ftest_cpdown(args->flags, WHED)) {
		err = au_cpdown_dir_opq(dentry, bdst, args);
		if (unlikely(err)) {
			mutex_unlock(&h_inode->i_mutex);
			goto out_dir;
		}
	}

	err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
	mutex_unlock(&h_inode->i_mutex);
	if (unlikely(err))
		goto out_opq;

	if (au_ftest_cpdown(args->flags, WHED)) {
		err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
		if (unlikely(err))
			goto out_opq;
	}

	inode = dentry->d_inode;
	if (au_ibend(inode) < bdst)
		au_set_ibend(inode, bdst);
	au_set_h_iptr(inode, bdst, au_igrab(h_inode),
		      au_hi_flags(inode, /*isdir*/1));
	goto out; /* success */

	/* revert */
out_opq:
	if (au_ftest_cpdown(args->flags, DIROPQ)) {
		mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
		rerr = au_diropq_remove(dentry, bdst);
		mutex_unlock(&h_inode->i_mutex);
		if (unlikely(rerr)) {
			AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
				AuDLNPair(dentry), bdst, rerr);
			err = -EIO;
			goto out;
		}
	}
out_dir:
	if (au_ftest_cpdown(args->flags, MADE_DIR)) {
		rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
		if (unlikely(rerr)) {
			AuIOErr("failed removing %.*s b%d (%d)\n",
				AuDLNPair(dentry), bdst, rerr);
			err = -EIO;
		}
	}
out_put:
	au_set_h_dptr(dentry, bdst, NULL);
	if (au_dbend(dentry) == bdst)
		au_update_dbend(dentry);
out:
	dput(parent);
	return err;
}