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; }
int au_do_pin(struct au_pin *p) { int err; struct super_block *sb; struct dentry *h_dentry, *h_parent; struct au_branch *br; struct inode *h_dir; err = 0; sb = p->dentry->d_sb; br = au_sbr(sb, p->bindex); if (IS_ROOT(p->dentry)) { if (au_ftest_pin(p->flags, MNT_WRITE)) { p->h_mnt = br->br_mnt; err = mnt_want_write(p->h_mnt); if (unlikely(err)) { au_fclr_pin(p->flags, MNT_WRITE); goto out_err; } } goto out; } h_dentry = NULL; if (p->bindex <= au_dbend(p->dentry)) h_dentry = au_h_dptr(p->dentry, p->bindex); p->parent = dget_parent(p->dentry); if (!au_ftest_pin(p->flags, DI_LOCKED)) di_read_lock(p->parent, AuLock_IR, p->lsc_di); h_dir = NULL; h_parent = au_h_dptr(p->parent, p->bindex); p->hdir = au_hi(p->parent->d_inode, p->bindex); if (p->hdir) h_dir = p->hdir->hi_inode; /* * udba case, or * if DI_LOCKED is not set, then p->parent may be different * and h_parent can be NULL. */ if (unlikely(!p->hdir || !h_dir || !h_parent)) { err = -EBUSY; if (!au_ftest_pin(p->flags, DI_LOCKED)) di_read_unlock(p->parent, AuLock_IR); dput(p->parent); p->parent = NULL; goto out_err; } au_igrab(h_dir); au_hn_imtx_lock_nested(p->hdir, p->lsc_hi); if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) { err = -EBUSY; goto out_unpin; } if (h_dentry) { err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br); if (unlikely(err)) { au_fclr_pin(p->flags, MNT_WRITE); goto out_unpin; } } if (au_ftest_pin(p->flags, MNT_WRITE)) { p->h_mnt = br->br_mnt; err = mnt_want_write(p->h_mnt); if (unlikely(err)) { au_fclr_pin(p->flags, MNT_WRITE); goto out_unpin; } } goto out; /* success */ out_unpin: au_unpin(p); out_err: pr_err("err %d\n", err); err = au_busy_or_stale(); out: return err; }