void di_downgrade_lock(struct dentry *d, int flags) { SiMustAnyLock(d->d_sb); au_rw_dgrade_lock(&au_di(d)->di_rwsem); if (d->d_inode && au_ftest_lock(flags, IR)) ii_downgrade_lock(d->d_inode); }
static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex, unsigned int sigen, const unsigned int verbose) { int err; unsigned long long max, ull; struct inode *i, **array; aufs_bindex_t bstart, bend; array = au_iarray_alloc(sb, &max); err = PTR_ERR(array); if (IS_ERR(array)) goto out; err = 0; AuDbg("b%d\n", bindex); for (ull = 0; !err && ull < max; ull++) { i = array[ull]; if (i->i_ino == AUFS_ROOT_INO) continue; /* AuDbgInode(i); */ if (au_iigen(i) == sigen) ii_read_lock_child(i); else { ii_write_lock_child(i); err = au_refresh_hinode_self(i); au_iigen_dec(i); if (!err) ii_downgrade_lock(i); else { ii_write_unlock(i); break; } } bstart = au_ibstart(i); bend = au_ibend(i); if (bstart <= bindex && bindex <= bend && au_h_iptr(i, bindex) && au_test_ibusy(i, bstart, bend)) { err = -EBUSY; AuVerbose(verbose, "busy i%lu\n", i->i_ino); AuDbgInode(i); } ii_read_unlock(i); } au_iarray_free(array, max); out: return err; }