Пример #1
0
/* lock them all */
static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a)
{
	int err;
	struct dentry *h_trap;

	a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc);
	a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst);
	if (a->mvd_h_src_sb != a->mvd_h_dst_sb) {
		a->rename_lock = 0;
		err = au_pin(&a->pin, a->dentry, a->mvd_bdst,
			     au_opt_udba(a->sb),
			     AuPin_MNT_WRITE | AuPin_DI_LOCKED);
		if (!err) {
			a->mvd_h_src_dir = a->mvd_h_src_parent->d_inode;
			mutex_lock_nested(&a->mvd_h_src_dir->i_mutex,
					  AuLsc_I_PARENT3);
		} else
			AU_MVD_PR(dmsg, "pin failed\n");
		goto out;
	}

	err = 0;
	a->rename_lock = 1;
	h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
				   a->mvd_h_dst_parent, a->mvd_hdir_dst);
	if (h_trap) {
		err = (h_trap != a->mvd_h_src_parent);
		if (err)
			err = (h_trap != a->mvd_h_dst_parent);
	}
	BUG_ON(err); /* it should never happen */

out:
	AuTraceErr(err);
	return err;
}
Пример #2
0
/* lock them all */
static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a)
{
    int err;
    struct dentry *h_trap;

    a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc);
    a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst);
    err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst,
                 au_opt_udba(a->sb),
                 AuPin_MNT_WRITE | AuPin_DI_LOCKED);
    AuTraceErr(err);
    if (unlikely(err)) {
        AU_MVD_PR(dmsg, "pin_dst failed\n");
        goto out;
    }

    if (a->mvd_h_src_sb != a->mvd_h_dst_sb) {
        a->rename_lock = 0;
        au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
                    AuLsc_DI_PARENT, AuLsc_I_PARENT3,
                    au_opt_udba(a->sb),
                    AuPin_MNT_WRITE | AuPin_DI_LOCKED);
        err = au_do_pin(&a->mvd_pin_src);
        AuTraceErr(err);
        a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
        if (unlikely(err)) {
            AU_MVD_PR(dmsg, "pin_src failed\n");
            goto out_dst;
        }
        goto out; /* success */
    }

    a->rename_lock = 1;
    au_pin_hdir_unlock(&a->mvd_pin_dst);
    err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
                 au_opt_udba(a->sb),
                 AuPin_MNT_WRITE | AuPin_DI_LOCKED);
    AuTraceErr(err);
    a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
    if (unlikely(err)) {
        AU_MVD_PR(dmsg, "pin_src failed\n");
        au_pin_hdir_lock(&a->mvd_pin_dst);
        goto out_dst;
    }
    au_pin_hdir_unlock(&a->mvd_pin_src);
    h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
                               a->mvd_h_dst_parent, a->mvd_hdir_dst);
    if (h_trap) {
        err = (h_trap != a->mvd_h_src_parent);
        if (err)
            err = (h_trap != a->mvd_h_dst_parent);
    }
    BUG_ON(err); /* it should never happen */
    if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) {
        err = -EBUSY;
        AuTraceErr(err);
        vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
                            a->mvd_h_dst_parent, a->mvd_hdir_dst);
        au_pin_hdir_lock(&a->mvd_pin_src);
        au_unpin(&a->mvd_pin_src);
        au_pin_hdir_lock(&a->mvd_pin_dst);
        goto out_dst;
    }
    goto out; /* success */

out_dst:
    au_unpin(&a->mvd_pin_dst);
out:
    AuTraceErr(err);
    return err;
}
int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
{
	int err, rerr, i;
	unsigned int mnt_flags;
	aufs_bindex_t bindex, bend, br_id;
	unsigned char do_wh, verbose;
	struct au_branch *br;
	struct au_wbr *wbr;

	err = 0;
	bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
	if (bindex < 0) {
		if (remount)
			goto out; /* success */
		err = -ENOENT;
		pr_err("%s no such branch\n", del->pathname);
		goto out;
	}
	AuDbg("bindex b%d\n", bindex);

	err = -EBUSY;
	mnt_flags = au_mntflags(sb);
	verbose = !!au_opt_test(mnt_flags, VERBOSE);
	bend = au_sbend(sb);
	if (unlikely(!bend)) {
		AuVerbose(verbose, "no more branches left\n");
		goto out;
	}
	br = au_sbr(sb, bindex);
	i = atomic_read(&br->br_count);
	if (unlikely(i)) {
		AuVerbose(verbose, "%d file(s) opened\n", i);
		goto out;
	}

	wbr = br->br_wbr;
	do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
	if (do_wh) {
		/* instead of WbrWhMustWriteLock(wbr) */
		SiMustWriteLock(sb);
		for (i = 0; i < AuBrWh_Last; i++) {
			dput(wbr->wbr_wh[i]);
			wbr->wbr_wh[i] = NULL;
		}
	}

	err = test_children_busy(sb->s_root, bindex, verbose);
	if (unlikely(err)) {
		if (do_wh)
			goto out_wh;
		goto out;
	}

	err = 0;
	br_id = br->br_id;
	if (!remount)
		au_br_do_del(sb, bindex, br);
	else {
		sysaufs_brs_del(sb, bindex);
		au_br_do_del(sb, bindex, br);
		sysaufs_brs_add(sb, bindex);
	}

	if (!bindex) {
		au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
		sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
	} else
		au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
	if (au_opt_test(mnt_flags, PLINK))
		au_plink_half_refresh(sb, br_id);

	if (au_xino_brid(sb) == br_id)
		au_xino_brid_set(sb, -1);
	goto out; /* success */

out_wh:
	/* revert */
	rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
	if (rerr)
		pr_warning("failed re-creating base whiteout, %s. (%d)\n",
			   del->pathname, rerr);
out:
	return err;
}