void au_fhsm_wrote_all(struct super_block *sb, int force) { aufs_bindex_t bindex, bend; struct au_branch *br; /* exclude the bottom */ bend = au_fhsm_bottom(sb); for (bindex = 0; bindex < bend; bindex++) { br = au_sbr(sb, bindex); if (au_br_fhsm(br->br_perm)) au_fhsm_wrote(sb, bindex, force); } }
static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst, struct au_pin *pin, struct dentry *h_parent, void *arg) { int err, rerr; aufs_bindex_t bopq, bstart; struct path h_path; struct dentry *parent; struct inode *h_dir, *h_inode, *inode, *dir; unsigned int *flags = arg; bstart = au_dbstart(dentry); /* dentry is di-locked */ parent = dget_parent(dentry); dir = parent->d_inode; h_dir = h_parent->d_inode; AuDebugOn(h_dir != au_h_iptr(dir, bdst)); IMustLock(h_dir); err = au_lkup_neg(dentry, bdst, /*wh*/0); if (unlikely(err < 0)) goto out; h_path.dentry = au_h_dptr(dentry, bdst); h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst); err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, S_IRWXU | S_IRUGO | S_IXUGO); if (unlikely(err)) goto out_put; au_fset_cpdown(*flags, MADE_DIR); bopq = au_dbdiropq(dentry); au_fclr_cpdown(*flags, WHED); au_fclr_cpdown(*flags, DIROPQ); if (au_dbwh(dentry) == bdst) au_fset_cpdown(*flags, WHED); if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst) au_fset_cpdown(*flags, PARENT_OPQ); h_inode = h_path.dentry->d_inode; mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); if (au_ftest_cpdown(*flags, WHED)) { err = au_cpdown_dir_opq(dentry, bdst, flags); if (unlikely(err)) { mutex_unlock(&h_inode->i_mutex); goto out_dir; } } err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart)); mutex_unlock(&h_inode->i_mutex); if (unlikely(err)) goto out_opq; if (au_ftest_cpdown(*flags, WHED)) { err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst); if (unlikely(err)) goto out_opq; } inode = dentry->d_inode; if (au_ibend(inode) < bdst) au_set_ibend(inode, bdst); au_set_h_iptr(inode, bdst, au_igrab(h_inode), au_hi_flags(inode, /*isdir*/1)); au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0); goto out; /* success */ /* revert */ out_opq: if (au_ftest_cpdown(*flags, DIROPQ)) { mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); rerr = au_diropq_remove(dentry, bdst); mutex_unlock(&h_inode->i_mutex); if (unlikely(rerr)) { AuIOErr("failed removing diropq for %.*s b%d (%d)\n", AuDLNPair(dentry), bdst, rerr); err = -EIO; goto out; } } out_dir: if (au_ftest_cpdown(*flags, MADE_DIR)) { rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path); if (unlikely(rerr)) { AuIOErr("failed removing %.*s b%d (%d)\n", AuDLNPair(dentry), bdst, rerr); err = -EIO; } } out_put: au_set_h_dptr(dentry, bdst, NULL); if (au_dbend(dentry) == bdst) au_update_dbend(dentry); out: dput(parent); return err; }