/* common function to regular file and dir */ int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), int wlock) { int err; unsigned int sigen, figen; aufs_bindex_t bstart; unsigned char pseudo_link; struct dentry *dentry; struct inode *inode; err = 0; dentry = file->f_dentry; inode = dentry->d_inode; AuDebugOn(au_special_file(inode->i_mode)); sigen = au_sigen(dentry->d_sb); fi_write_lock(file); figen = au_figen(file); di_write_lock_child(dentry); bstart = au_dbstart(dentry); pseudo_link = (bstart != au_ibstart(inode)); if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) { if (!wlock) { di_downgrade_lock(dentry, AuLock_IR); fi_downgrade_lock(file); } goto out; /* success */ } AuDbg("sigen %d, figen %d\n", sigen, figen); if (sigen != au_digen(dentry) || sigen != au_iigen(inode)) { err = au_reval_dpath(dentry, sigen); if (unlikely(err < 0)) goto out; AuDebugOn(au_digen(dentry) != sigen || au_iigen(inode) != sigen); } err = refresh_file(file, reopen); if (!err) { if (!wlock) { di_downgrade_lock(dentry, AuLock_IR); fi_downgrade_lock(file); } } else { di_write_unlock(dentry); fi_write_unlock(file); } out: return err; }
static int do_pri_file(aufs_bindex_t bindex, struct file *file) { char a[32]; if (!file || IS_ERR(file)) { dpri("f%d: err %ld\n", bindex, PTR_ERR(file)); return -1; } a[0] = 0; if (bindex < 0 && file->f_dentry && au_test_aufs(file->f_dentry->d_sb) && au_fi(file)) snprintf(a, sizeof(a), ", gen %d, mmapped %d", au_figen(file), atomic_read(&au_fi(file)->fi_mmapped)); dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n", bindex, file->f_mode, file->f_flags, (long)file_count(file), file->f_version, file->f_pos, a); if (file->f_dentry) do_pri_dentry(bindex, file->f_dentry); return 0; }
static int au_rdu(struct file *file, struct aufs_rdu *rdu) { int err; aufs_bindex_t bend; struct au_rdu_arg arg; struct dentry *dentry; struct inode *inode; struct file *h_file; struct au_rdu_cookie *cookie = &rdu->cookie; err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz); if (unlikely(err)) { err = -EFAULT; AuTraceErr(err); goto out; } rdu->rent = 0; rdu->tail = rdu->ent; rdu->full = 0; arg.rdu = rdu; arg.ent = rdu->ent; arg.end = arg.ent.ul; arg.end += rdu->sz; err = -ENOTDIR; if (unlikely(!file->f_op || !file->f_op->readdir)) goto out; err = security_file_permission(file, MAY_READ); AuTraceErr(err); if (unlikely(err)) goto out; dentry = file->f_dentry; inode = dentry->d_inode; #if 1 mutex_lock(&inode->i_mutex); #else err = mutex_lock_killable(&inode->i_mutex); AuTraceErr(err); if (unlikely(err)) goto out; #endif err = -ENOENT; if (unlikely(IS_DEADDIR(inode))) goto out_mtx; arg.sb = inode->i_sb; si_read_lock(arg.sb, AuLock_FLUSH); fi_read_lock(file); err = -EAGAIN; if (unlikely(au_ftest_rdu(cookie->flags, CONT) && cookie->generation != au_figen(file))) goto out_unlock; err = 0; if (!rdu->blk) { rdu->blk = au_sbi(arg.sb)->si_rdblk; if (!rdu->blk) rdu->blk = au_dir_size(file, /*dentry*/NULL); } bend = au_fbstart(file); if (cookie->bindex < bend) cookie->bindex = bend; bend = au_fbend_dir(file); /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */ for (; !err && cookie->bindex <= bend; cookie->bindex++, cookie->h_pos = 0) { h_file = au_hf_dir(file, cookie->bindex); if (!h_file) continue; au_fclr_rdu(cookie->flags, FULL); err = au_rdu_do(h_file, &arg); AuTraceErr(err); if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err)) break; } AuDbg("rent %llu\n", rdu->rent); if (!err && !au_ftest_rdu(cookie->flags, CONT)) { rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH); au_fset_rdu(cookie->flags, CONT); cookie->generation = au_figen(file); } ii_read_lock_child(inode); fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode))); ii_read_unlock(inode); out_unlock: fi_read_unlock(file); si_read_unlock(arg.sb); out_mtx: mutex_unlock(&inode->i_mutex); out: AuTraceErr(err); return err; }