Example #1
0
static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a)
{
	if (!a->rename_lock) {
		mutex_unlock(&a->mvd_h_src_dir->i_mutex);
		au_unpin(&a->pin);
	} else
		vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
				    a->mvd_h_dst_parent, a->mvd_hdir_dst);
}
/*
 * locking order
 * (VFS)
 * - src_dir and dir by lock_rename()
 * - inode if exitsts
 * (aufs)
 * - lock all
 *   + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
 *     + si_read_lock
 *     + di_write_lock2_child()
 *       + di_write_lock_child()
 *	   + ii_write_lock_child()
 *       + di_write_lock_child2()
 *	   + ii_write_lock_child2()
 *     + src_parent and parent
 *       + di_write_lock_parent()
 *	   + ii_write_lock_parent()
 *       + di_write_lock_parent2()
 *	   + ii_write_lock_parent2()
 *   + lower src_dir and dir by vfsub_lock_rename()
 *   + verify the every relationships between child and parent. if any
 *     of them failed, unlock all and return -EBUSY.
 */
static void au_ren_unlock(struct au_ren_args *a)
{
	struct super_block *sb;

	sb = a->dst_dentry->d_sb;
	if (au_ftest_ren(a->flags, MNT_WRITE))
		mnt_drop_write(a->br->br_mnt);
	vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
			    a->dst_h_parent, a->dst_hdir);
}
Example #3
0
static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a)
{
    if (!a->rename_lock)
        au_unpin(&a->mvd_pin_src);
    else {
        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);
    }
    au_unpin(&a->mvd_pin_dst);
}
Example #4
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;
}