/* * 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_dbtop(a->dentry, a->mvd_bdst); au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0); au_set_ibtop(a->inode, a->mvd_bdst); } else { /* hide the lower */ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL); au_set_dbbot(a->dentry, a->mvd_bsrc); au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0); au_set_ibbot(a->inode, a->mvd_bsrc); } if (au_dbbot(a->dentry) < a->mvd_bdst) au_set_dbbot(a->dentry, a->mvd_bdst); if (au_ibbot(a->inode) < a->mvd_bdst) au_set_ibbot(a->inode, a->mvd_bdst); out_unlock: au_do_unlock(dmsg, a); out: AuTraceErr(err); return err; }
static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a) { int err; struct au_branch *br; err = -EISDIR; if (unlikely(S_ISDIR(a->inode->i_mode))) goto out; err = -EINVAL; if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER)) a->mvd_bsrc = au_ibstart(a->inode); else { a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid); if (unlikely(a->mvd_bsrc < 0 || (a->mvd_bsrc < au_dbstart(a->dentry) || au_dbend(a->dentry) < a->mvd_bsrc || !au_h_dptr(a->dentry, a->mvd_bsrc)) || (a->mvd_bsrc < au_ibstart(a->inode) || au_ibend(a->inode) < a->mvd_bsrc || !au_h_iptr(a->inode, a->mvd_bsrc)))) { a->mvd_errno = EAU_MVDOWN_NOUPPER; AU_MVD_PR(dmsg, "no upper\n"); goto out; } } if (unlikely(a->mvd_bsrc == au_sbend(a->sb))) { a->mvd_errno = EAU_MVDOWN_BOTTOM; AU_MVD_PR(dmsg, "on the bottom\n"); goto out; } a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc); br = au_sbr(a->sb, a->mvd_bsrc); err = au_br_rdonly(br); if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) { if (unlikely(err)) goto out; } else if (!(vfsub_native_ro(a->mvd_h_src_inode) || IS_APPEND(a->mvd_h_src_inode))) { if (err) a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R; /* go on */ } else goto out; err = -EINVAL; if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) { a->mvd_bdst = find_lower_writable(a); if (unlikely(a->mvd_bdst < 0)) { a->mvd_errno = EAU_MVDOWN_BOTTOM; AU_MVD_PR(dmsg, "no writable lower branch\n"); goto out; } } else { a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid); if (unlikely(a->mvd_bdst < 0 || au_sbend(a->sb) < a->mvd_bdst)) { a->mvd_errno = EAU_MVDOWN_NOLOWERBR; AU_MVD_PR(dmsg, "no lower brid\n"); goto out; } } err = au_mvd_args_busy(dmsg, a); if (!err) err = au_mvd_args_parent(dmsg, a); if (!err) err = au_mvd_args_intermediate(dmsg, a); if (!err) err = au_mvd_args_exist(dmsg, a); if (!err) AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst); out: AuTraceErr(err); return err; }