static int au_hide_children(struct dentry *parent) { int err, i, j, ndentry; struct au_dcsub_pages dpages; struct au_dpage *dpage; struct dentry *dentry; err = au_dpages_init(&dpages, GFP_NOFS); if (unlikely(err)) goto out; err = au_dcsub_pages(&dpages, parent, NULL, NULL); if (unlikely(err)) goto out_dpages; /* in reverse order */ for (i = dpages.ndpage - 1; i >= 0; i--) { dpage = dpages.dpages + i; ndentry = dpage->ndentry; for (j = ndentry - 1; j >= 0; j--) { dentry = dpage->dentries[j]; if (dentry != parent) au_do_hide(dentry); } } out_dpages: au_dpages_free(&dpages); out: return err; }
int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst) { int err; struct au_cpdown_dir_args args = { .parent = dget_parent(dentry), .flags = 0 }; err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args); dput(args.parent); return err; } /* ---------------------------------------------------------------------- */ /* policies for create */ static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex) { int err, i, j, ndentry; aufs_bindex_t bopq; struct au_dcsub_pages dpages; struct au_dpage *dpage; struct dentry **dentries, *parent, *d; err = au_dpages_init(&dpages, GFP_NOFS); if (unlikely(err)) goto out; parent = dget_parent(dentry); err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/0, /*test*/NULL, /*arg*/NULL); if (unlikely(err)) goto out_free; err = bindex; for (i = 0; i < dpages.ndpage; i++) { dpage = dpages.dpages + i; dentries = dpage->dentries; ndentry = dpage->ndentry; for (j = 0; j < ndentry; j++) { d = dentries[j]; di_read_lock_parent2(d, !AuLock_IR); bopq = au_dbdiropq(d); di_read_unlock(d, !AuLock_IR); if (bopq >= 0 && bopq < err) err = bopq; } } out_free: dput(parent); au_dpages_free(&dpages); out: return err; }
void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen) { int err, i, j; struct au_dcsub_pages dpages; struct au_dpage *dpage; struct dentry **dentries; err = au_dpages_init(&dpages, GFP_NOFS); AuDebugOn(err); err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1); AuDebugOn(err); for (i = dpages.ndpage - 1; !err && i >= 0; i--) { dpage = dpages.dpages + i; dentries = dpage->dentries; for (j = dpage->ndentry - 1; !err && j >= 0; j--) AuDebugOn(au_digen_test(dentries[j], sigen)); } au_dpages_free(&dpages); }
int au_is_subdir(struct dentry *d1, struct dentry *d2) { int err; #ifndef AuUse_ISSUBDIR int i, j; struct au_dcsub_pages dpages; struct au_dpage *dpage; struct dentry **dentries; #endif LKTRTrace("%.*s, %.*s\n", DLNPair(d1), DLNPair(d2)); #ifdef AuUse_ISSUBDIR spin_lock(&dcache_lock); err = is_subdir(d1, d2); spin_unlock(&dcache_lock); #else err = au_dpages_init(&dpages, GFP_KERNEL); if (unlikely(err)) goto out; err = au_dcsub_pages_rev(&dpages, d1, /*do_include*/1, NULL, NULL); if (unlikely(err)) goto out_dpages; for (i = dpages.ndpage - 1; !err && i >= 0; i--) { dpage = dpages.dpages + i; dentries = dpage->dentries; for (j = dpage->ndentry - 1; !err && j >= 0; j--) { struct dentry *d; d = dentries[j]; //Dbg("d %.*s\n", DLNPair(d)); err = (d == d2); } } out_dpages: au_dpages_free(&dpages); out: #endif TraceErr(err); return err; }
static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex) { int err, i, j, ndentry; aufs_bindex_t bopq; struct au_dcsub_pages dpages; struct au_dpage *dpage; struct dentry **dentries, *parent, *d; err = au_dpages_init(&dpages, GFP_NOFS); if (unlikely(err)) goto out; parent = dget_parent(dentry); err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0); if (unlikely(err)) goto out_free; err = bindex; for (i = 0; i < dpages.ndpage; i++) { dpage = dpages.dpages + i; dentries = dpage->dentries; ndentry = dpage->ndentry; for (j = 0; j < ndentry; j++) { d = dentries[j]; di_read_lock_parent2(d, !AuLock_IR); bopq = au_dbdiropq(d); di_read_unlock(d, !AuLock_IR); if (bopq >= 0 && bopq < err) err = bopq; } } out_free: dput(parent); au_dpages_free(&dpages); out: return err; }
/* * test if the branch is deletable or not. */ static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex, unsigned int sigen, const unsigned int verbose) { int err, i, j, ndentry; aufs_bindex_t bstart, bend; struct au_dcsub_pages dpages; struct au_dpage *dpage; struct dentry *d; err = au_dpages_init(&dpages, GFP_NOFS); if (unlikely(err)) goto out; err = au_dcsub_pages(&dpages, root, NULL, NULL); if (unlikely(err)) goto out_dpages; for (i = 0; !err && i < dpages.ndpage; i++) { dpage = dpages.dpages + i; ndentry = dpage->ndentry; for (j = 0; !err && j < ndentry; j++) { d = dpage->dentries[j]; AuDebugOn(!atomic_read(&d->d_count)); if (!au_digen_test(d, sigen)) { di_read_lock_child(d, AuLock_IR); if (unlikely(au_dbrange_test(d))) { di_read_unlock(d, AuLock_IR); continue; } } else { di_write_lock_child(d); if (unlikely(au_dbrange_test(d))) { di_write_unlock(d); continue; } err = au_reval_dpath(d, sigen); if (!err) di_downgrade_lock(d, AuLock_IR); else { di_write_unlock(d); break; } } /* AuDbgDentry(d); */ bstart = au_dbstart(d); bend = au_dbend(d); if (bstart <= bindex && bindex <= bend && au_h_dptr(d, bindex) && au_test_dbusy(d, bstart, bend)) { err = -EBUSY; AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d)); AuDbgDentry(d); } di_read_unlock(d, AuLock_IR); } } out_dpages: au_dpages_free(&dpages); out: return err; }