static int au_ren_lock(struct au_ren_args *a)
{
	int err;
	unsigned int udba;

	err = 0;
	a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
	a->src_hdir = au_hi(a->src_dir, a->btgt);
	a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
	a->dst_hdir = au_hi(a->dst_dir, a->btgt);
	a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
				      a->dst_h_parent, a->dst_hdir);
	udba = au_opt_udba(a->src_dentry->d_sb);
	if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
		     || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
		err = au_busy_or_stale();
	if (!err && au_dbstart(a->src_dentry) == a->btgt)
		err = au_h_verify(a->src_h_dentry, udba,
				  a->src_h_parent->d_inode, a->src_h_parent,
				  a->br);
	if (!err && au_dbstart(a->dst_dentry) == a->btgt)
		err = au_h_verify(a->dst_h_dentry, udba,
				  a->dst_h_parent->d_inode, a->dst_h_parent,
				  a->br);
	if (!err) {
		err = mnt_want_write(a->br->br_mnt);
		if (unlikely(err))
			goto out_unlock;
		au_fset_ren(a->flags, MNT_WRITE);
		goto out; /* success */
	}

	err = au_busy_or_stale();

out_unlock:
	au_ren_unlock(a);
out:
	return err;
}
Ejemplo n.º 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);
	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;
}
Ejemplo n.º 3
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;
}