static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { ssize_t err; int readable; aufs_bindex_t nfhsm, bindex, bend; struct au_sbinfo *sbinfo; struct au_fhsm *fhsm; struct au_branch *br; struct super_block *sb; err = 0; sbinfo = file->private_data; fhsm = &sbinfo->si_fhsm; need_data: spin_lock_irq(&fhsm->fhsm_wqh.lock); if (!atomic_read(&fhsm->fhsm_readable)) { if (vfsub_file_flags(file) & O_NONBLOCK) err = -EAGAIN; else err = wait_event_interruptible_locked_irq (fhsm->fhsm_wqh, atomic_read(&fhsm->fhsm_readable)); } spin_unlock_irq(&fhsm->fhsm_wqh.lock); if (unlikely(err)) goto out; /* sb may already be dead */ au_rw_read_lock(&sbinfo->si_rwsem); readable = atomic_read(&fhsm->fhsm_readable); if (readable > 0) { sb = sbinfo->si_sb; AuDebugOn(!sb); /* exclude the bottom branch */ nfhsm = 0; bend = au_fhsm_bottom(sb); for (bindex = 0; bindex < bend; bindex++) { br = au_sbr(sb, bindex); if (au_br_fhsm(br->br_perm)) nfhsm++; } err = -EMSGSIZE; if (nfhsm * sizeof(struct aufs_stbr) <= count) { atomic_set(&fhsm->fhsm_readable, 0); err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf, count); } } au_rw_read_unlock(&sbinfo->si_rwsem); if (!readable) goto need_data; out: return err; }
void di_read_unlock(struct dentry *d, int flags) { if (d->d_inode) { if (au_ftest_lock(flags, IW)) ii_write_unlock(d->d_inode); else if (au_ftest_lock(flags, IR)) ii_read_unlock(d->d_inode); } au_rw_read_unlock(&au_di(d)->di_rwsem); }
void di_read_unlock(struct dentry *d, int flags) { if (d->d_inode) { if (au_ftest_lock(flags, IW)) { au_dbg_verify_dinode(d); ii_write_unlock(d->d_inode); } else if (au_ftest_lock(flags, IR)) { au_dbg_verify_dinode(d); ii_read_unlock(d->d_inode); } } au_rw_read_unlock(&au_di(d)->di_rwsem); }
void di_read_unlock(struct dentry *d, int flags) { LKTRTrace("%.*s\n", AuDLNPair(d)); SiMustAnyLock(d->d_sb); if (d->d_inode) { if (au_ftest_lock(flags, IW)) ii_write_unlock(d->d_inode); else if (au_ftest_lock(flags, IR)) ii_read_unlock(d->d_inode); } au_rw_read_unlock(&au_di(d)->di_rwsem); au_dbg_locked_di_unreg(d, flags); }