コード例 #1
0
int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
{
	int err;
	unsigned int sigen;
	struct super_block *sb;

	sb = d1->d_sb;
	err = si_read_lock(sb, flags);
	if (unlikely(err))
		goto out;

	di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));

	if (au_ftest_lock(flags, GEN)) {
		sigen = au_sigen(sb);
		err = au_digen_test(d1, sigen);
		AuDebugOn(!err && au_dbrange_test(d1));
		if (!err) {
			err = au_digen_test(d2, sigen);
			AuDebugOn(!err && au_dbrange_test(d2));
		}
		if (unlikely(err))
			aufs_read_and_write_unlock2(d1, d2);
	}

out:
	return err;
}
コード例 #2
0
ファイル: f_op_sp.c プロジェクト: aywq2008/omniplay
static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
				unsigned long nv, loff_t pos)
{
	ssize_t err;
	aufs_bindex_t bstart;
	unsigned char wbr;
	struct file *file, *h_file;
	struct super_block *sb;

	file = kio->ki_filp;
	sb = file->f_dentry->d_sb;
	si_read_lock(sb, AuLock_FLUSH);
	fi_read_lock(file);
	bstart = au_fbstart(file);
	h_file = au_hf_top(file);
	fi_read_unlock(file);
	wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
	si_read_unlock(sb);

	/* do not change the file in kio */
	AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
	err = h_file->f_op->aio_read(kio, iov, nv, pos);
	if (err > 0 && wbr)
		file_accessed(h_file);

	return err;
}
コード例 #3
0
/* dentry and super_block lock. call at entry point */
int aufs_read_lock(struct dentry *dentry, int flags)
{
	int err;
	struct super_block *sb;

	sb = dentry->d_sb;
	err = si_read_lock(sb, flags);
	if (unlikely(err))
		goto out;

	if (au_ftest_lock(flags, DW))
		di_write_lock_child(dentry);
	else
		di_read_lock_child(dentry, flags);

	if (au_ftest_lock(flags, GEN)) {
		err = au_digen_test(dentry, au_sigen(sb));
		AuDebugOn(!err && au_dbrange_test(dentry));
		if (unlikely(err))
			aufs_read_unlock(dentry, flags);
	}

out:
	return err;
}
コード例 #4
0
/* dentry and super_block lock. call at entry point */
void aufs_read_lock(struct dentry *dentry, int flags)
{
	si_read_lock(dentry->d_sb);
	if (flags & AUFS_D_WLOCK)
		di_write_lock_child(dentry);
	else
		di_read_lock_child(dentry, flags);
}
コード例 #5
0
ファイル: sbinfo.c プロジェクト: chrmorais/miniemc2
/* dentry and super_block lock. call at entry point */
void aufs_read_lock(struct dentry *dentry, int flags)
{
	si_read_lock(dentry->d_sb, flags);
	if (au_ftest_lock(flags, DW))
		di_write_lock_child(dentry);
	else
		di_read_lock_child(dentry, flags);
}
コード例 #6
0
static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
{
	int err;
	aufs_bindex_t bstart, bend;
	struct aufs_ibusy ibusy;
	struct inode *inode, *h_inode;

	err = -EPERM;
	if (unlikely(!capable(CAP_SYS_ADMIN)))
		goto out;

	err = copy_from_user(&ibusy, arg, sizeof(ibusy));
	if (!err)
		err = !access_ok(VERIFY_WRITE, &arg->h_ino, sizeof(arg->h_ino));
	if (unlikely(err)) {
		err = -EFAULT;
		AuTraceErr(err);
		goto out;
	}

	err = -EINVAL;
	si_read_lock(sb, AuLock_FLUSH);
	if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbend(sb)))
		goto out_unlock;

	err = 0;
	ibusy.h_ino = 0; /* invalid */
	inode = ilookup(sb, ibusy.ino);
	if (!inode
	    || inode->i_ino == AUFS_ROOT_INO
	    || is_bad_inode(inode))
		goto out_unlock;

	ii_read_lock_child(inode);
	bstart = au_ibstart(inode);
	bend = au_ibend(inode);
	if (bstart <= ibusy.bindex && ibusy.bindex <= bend) {
		h_inode = au_h_iptr(inode, ibusy.bindex);
		if (h_inode && au_test_ibusy(inode, bstart, bend))
			ibusy.h_ino = h_inode->i_ino;
	}
	ii_read_unlock(inode);
	iput(inode);

out_unlock:
	si_read_unlock(sb);
	if (!err) {
		err = __put_user(ibusy.h_ino, &arg->h_ino);
		if (unlikely(err)) {
			err = -EFAULT;
			AuTraceErr(err);
		}
	}
out:
	return err;
}
コード例 #7
0
ファイル: export.c プロジェクト: roalex/bravo-kernel
static int aufs_commit_metadata(struct inode *inode)
{
	int err;
	aufs_bindex_t bindex;
	struct super_block *sb;
	struct inode *h_inode;
	int (*f)(struct inode *inode);

	sb = inode->i_sb;
	si_read_lock(sb, AuLock_FLUSH);
	ii_write_lock_child(inode);
	bindex = au_ibstart(inode);
	AuDebugOn(bindex < 0);
	h_inode = au_h_iptr(inode, bindex);

	f = h_inode->i_sb->s_export_op->commit_metadata;
	if (f)
		err = f(h_inode);
	else {
		struct writeback_control wbc = {
			.sync_mode	= WB_SYNC_ALL,
			.nr_to_write	= 0 /* metadata only */
		};

		err = sync_inode(h_inode, &wbc);
	}

	au_cpup_attr_timesizes(inode);
	ii_write_unlock(inode);
	si_read_unlock(sb);
	return err;
}

/* ---------------------------------------------------------------------- */

static struct export_operations aufs_export_op = {
	.fh_to_dentry		= aufs_fh_to_dentry,
	/* .fh_to_parent	= aufs_fh_to_parent, */
	.encode_fh		= aufs_encode_fh,
	.commit_metadata	= aufs_commit_metadata
};

void au_export_init(struct super_block *sb)
{
	struct au_sbinfo *sbinfo;
	__u32 u;

	sb->s_export_op = &aufs_export_op;
	sbinfo = au_sbi(sb);
	sbinfo->si_xigen = NULL;
	get_random_bytes(&u, sizeof(u));
	BUILD_BUG_ON(sizeof(u) != sizeof(int));
	atomic_set(&sbinfo->si_xigen_next, u);
}
コード例 #8
0
ファイル: i_op.c プロジェクト: roalex/bravo-kernel
static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
				  struct nameidata *nd)
{
	struct dentry *ret, *parent;
	struct inode *inode;
	struct super_block *sb;
	int err, npositive;

	IMustLock(dir);

	sb = dir->i_sb;
	si_read_lock(sb, AuLock_FLUSH);
	ret = ERR_PTR(-ENAMETOOLONG);
	if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
		goto out;
	err = au_di_init(dentry);
	ret = ERR_PTR(err);
	if (unlikely(err))
		goto out;

	parent = dentry->d_parent; /* dir inode is locked */
	di_read_lock_parent(parent, AuLock_IR);
	npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
	di_read_unlock(parent, AuLock_IR);
	err = npositive;
	ret = ERR_PTR(err);
	if (unlikely(err < 0))
		goto out_unlock;

	inode = NULL;
	if (npositive) {
		inode = au_new_inode(dentry, /*must_new*/0);
		ret = (void *)inode;
	}
	if (IS_ERR(inode))
		goto out_unlock;

	ret = d_splice_alias(inode, dentry);
	if (unlikely(IS_ERR(ret) && inode))
		ii_write_unlock(inode);

 out_unlock:
	di_write_unlock(dentry);
 out:
	si_read_unlock(sb);
	return ret;
}
コード例 #9
0
ファイル: rdu.c プロジェクト: chrmorais/miniemc2
static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
{
	int err;
	ino_t ino;
	unsigned long long nent;
	union au_rdu_ent_ul *u;
	struct au_rdu_ent ent;
	struct super_block *sb;

	err = 0;
	nent = rdu->nent;
	u = &rdu->ent;
	sb = file->f_dentry->d_sb;
	si_read_lock(sb, AuLock_FLUSH);
	while (nent-- > 0) {
		err = copy_from_user(&ent, u->e, sizeof(ent));
		if (!err)
			err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
		if (unlikely(err)) {
			err = -EFAULT;
			AuTraceErr(err);
			break;
		}

		/* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
		if (!ent.wh)
			err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
		else
			err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
					&ino);
		if (unlikely(err)) {
			AuTraceErr(err);
			break;
		}

		err = __put_user(ino, &u->e->ino);
		if (unlikely(err)) {
			err = -EFAULT;
			AuTraceErr(err);
			break;
		}
		u->ul += au_rdu_len(ent.nlen);
	}
	si_read_unlock(sb);

	return err;
}
コード例 #10
0
ファイル: export.c プロジェクト: roalex/bravo-kernel
static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
				       struct au_nfsd_si_lock *nsi_lock)
{
	aufs_bindex_t bindex;

	si_read_lock(sb, AuLock_FLUSH);

	/* branch id may be wrapped around */
	bindex = au_br_index(sb, nsi_lock->br_id);
	if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
		goto out; /* success */

	if (!nsi_lock->force_lock)
		si_read_unlock(sb);
	bindex = -1;

 out:
	return bindex;
}
コード例 #11
0
ファイル: file.c プロジェクト: bojosos/linux
int au_do_open(struct file *file, int (*open)(struct file *file, int flags))
{
	int err;
	struct dentry *dentry;
	struct super_block *sb;

	dentry = file->f_dentry;
	sb = dentry->d_sb;
	si_read_lock(sb, AuLock_FLUSH);
	err = au_finfo_init(file);
	if (unlikely(err))
		goto out;

	di_read_lock_child(dentry, AuLock_IR);
	err = open(file, vfsub_file_flags(file));
	di_read_unlock(dentry, AuLock_IR);

	fi_write_unlock(file);
	if (unlikely(err))
		au_finfo_fin(file);
 out:
	si_read_unlock(sb);
	return err;
}
コード例 #12
0
static int aufs_permission(struct inode *inode, int mask)
{
	int err;
	aufs_bindex_t bindex, bend;
	const unsigned char isdir = !!S_ISDIR(inode->i_mode),
		write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
	struct inode *h_inode;
	struct super_block *sb;
	struct au_branch *br;

	/* todo: support rcu-walk? */
	if (mask & MAY_NOT_BLOCK)
		return -ECHILD;

	sb = inode->i_sb;
	si_read_lock(sb, AuLock_FLUSH);
	ii_read_lock_child(inode);
#if 0
	err = au_iigen_test(inode, au_sigen(sb));
	if (unlikely(err))
		goto out;
#endif

	if (!isdir || write_mask) {
		err = au_busy_or_stale();
		h_inode = au_h_iptr(inode, au_ibstart(inode));
		if (unlikely(!h_inode
			     || (h_inode->i_mode & S_IFMT)
			     != (inode->i_mode & S_IFMT)))
			goto out;

		err = 0;
		bindex = au_ibstart(inode);
		br = au_sbr(sb, bindex);
		err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
		if (write_mask
		    && !err
		    && !special_file(h_inode->i_mode)) {
			/* test whether the upper writable branch exists */
			err = -EROFS;
			for (; bindex >= 0; bindex--)
				if (!au_br_rdonly(au_sbr(sb, bindex))) {
					err = 0;
					break;
				}
		}
		goto out;
	}

	/* non-write to dir */
	err = 0;
	bend = au_ibend(inode);
	for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
		h_inode = au_h_iptr(inode, bindex);
		if (h_inode) {
			err = au_busy_or_stale();
			if (unlikely(!S_ISDIR(h_inode->i_mode)))
				break;

			br = au_sbr(sb, bindex);
			err = h_permission(h_inode, mask, br->br_mnt,
					   br->br_perm);
		}
	}

out:
	ii_read_unlock(inode);
	si_read_unlock(sb);
	return err;
}
コード例 #13
0
ファイル: i_op.c プロジェクト: ammubhave/bargud
static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
				  unsigned int flags)
{
	struct dentry *ret, *parent;
	struct inode *inode;
	struct super_block *sb;
	int err, npositive;

	IMustLock(dir);

	/* todo: support rcu-walk? */
	ret = ERR_PTR(-ECHILD);
	if (flags & LOOKUP_RCU)
		goto out;

	ret = ERR_PTR(-ENAMETOOLONG);
	if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
		goto out;

	sb = dir->i_sb;
	err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
	ret = ERR_PTR(err);
	if (unlikely(err))
		goto out;

	err = au_di_init(dentry);
	ret = ERR_PTR(err);
	if (unlikely(err))
		goto out_si;

	inode = NULL;
	npositive = 0; /* suppress a warning */
	parent = dentry->d_parent; /* dir inode is locked */
	di_read_lock_parent(parent, AuLock_IR);
	err = au_alive_dir(parent);
	if (!err)
		err = au_digen_test(parent, au_sigen(sb));
	if (!err) {
		npositive = au_lkup_dentry(dentry, au_dbstart(parent),
					   /*type*/0);
		err = npositive;
	}
	di_read_unlock(parent, AuLock_IR);
	ret = ERR_PTR(err);
	if (unlikely(err < 0))
		goto out_unlock;

	if (npositive) {
		inode = au_new_inode(dentry, /*must_new*/0);
		if (IS_ERR(inode)) {
			ret = (void *)inode;
			inode = NULL;
			goto out_unlock;
		}
	}

	if (inode)
		atomic_inc(&inode->i_count);
	ret = d_splice_alias(inode, dentry);
#if 0
	if (unlikely(d_need_lookup(dentry))) {
		spin_lock(&dentry->d_lock);
		dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
		spin_unlock(&dentry->d_lock);
	} else
#endif
	if (inode) {
		if (!IS_ERR(ret)) {
			iput(inode);
			if (ret && ret != dentry)
				ii_write_unlock(inode);
		} else {
			ii_write_unlock(inode);
			iput(inode);
			inode = NULL;
		}
	}

out_unlock:
	di_write_unlock(dentry);
	if (inode) {
		/* verbose coding for lock class name */
		if (unlikely(S_ISLNK(inode->i_mode)))
			au_rw_class(&au_di(dentry)->di_rwsem,
				    au_lc_key + AuLcSymlink_DIINFO);
		else if (unlikely(S_ISDIR(inode->i_mode)))
			au_rw_class(&au_di(dentry)->di_rwsem,
				    au_lc_key + AuLcDir_DIINFO);
		else /* likely */
			au_rw_class(&au_di(dentry)->di_rwsem,
				    au_lc_key + AuLcNonDir_DIINFO);
	}
out_si:
	si_read_unlock(sb);
out:
	return ret;
}
コード例 #14
0
static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
				  struct nameidata *nd)
{
	struct dentry *ret, *parent;
	struct inode *inode;
	struct super_block *sb;
	int err, npositive, lc_idx;

	IMustLock(dir);

	sb = dir->i_sb;
	err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
	ret = ERR_PTR(err);
	if (unlikely(err))
		goto out;

	ret = ERR_PTR(-ENAMETOOLONG);
	if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
		goto out_si;
	err = au_di_init(dentry);
	ret = ERR_PTR(err);
	if (unlikely(err))
		goto out_si;

	inode = NULL;
	npositive = 0; /* suppress a warning */
	parent = dentry->d_parent; /* dir inode is locked */
	di_read_lock_parent(parent, AuLock_IR);
	err = au_alive_dir(parent);
	if (!err)
		err = au_digen_test(parent, au_sigen(sb));
	if (!err) {
		npositive = au_lkup_dentry(dentry, au_dbstart(parent),
					   /*type*/0, nd);
		err = npositive;
	}
	di_read_unlock(parent, AuLock_IR);
	ret = ERR_PTR(err);
	if (unlikely(err < 0))
		goto out_unlock;

	if (npositive) {
		inode = au_new_inode(dentry, /*must_new*/0);
		ret = (void *)inode;
	}
	if (IS_ERR(inode)) {
		inode = NULL;
		goto out_unlock;
	}

	ret = d_splice_alias(inode, dentry);
	if (unlikely(IS_ERR(ret) && inode)) {
		ii_write_unlock(inode);
		lc_idx = AuLcNonDir_IIINFO;
		if (S_ISLNK(inode->i_mode))
			lc_idx = AuLcSymlink_IIINFO;
		else if (S_ISDIR(inode->i_mode))
			lc_idx = AuLcDir_IIINFO;
		au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + lc_idx);
		iput(inode);
	}

out_unlock:
	di_write_unlock(dentry);
	if (unlikely(IS_ERR(ret) && inode)) {
		lc_idx = AuLcNonDir_DIINFO;
		if (S_ISLNK(inode->i_mode))
			lc_idx = AuLcSymlink_DIINFO;
		else if (S_ISDIR(inode->i_mode))
			lc_idx = AuLcDir_DIINFO;
		au_rw_class(&au_di(dentry)->di_rwsem, au_lc_key + lc_idx);
	}
out_si:
	si_read_unlock(sb);
out:
	return ret;
}
コード例 #15
0
ファイル: rdu.c プロジェクト: chrmorais/miniemc2
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;
}
コード例 #16
0
ファイル: sbinfo.c プロジェクト: chrmorais/miniemc2
void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
{
	si_read_lock(d1->d_sb, flags);
	di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
}
コード例 #17
0
void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir)
{
	AuDebugOn(d1 == d2 || d1->d_sb != d2->d_sb);
	si_read_lock(d1->d_sb);
	di_write_lock2_child(d1, d2, isdir);
}
コード例 #18
0
ファイル: i_op.c プロジェクト: JanLuca/aufs4-debian
static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
				  unsigned int flags)
{
	struct dentry *ret, *parent;
	struct inode *inode;
	struct super_block *sb;
	int err, npositive;

	IMustLock(dir);

	/* todo: support rcu-walk? */
	ret = ERR_PTR(-ECHILD);
	if (flags & LOOKUP_RCU)
		goto out;

	ret = ERR_PTR(-ENAMETOOLONG);
	if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
		goto out;

	sb = dir->i_sb;
	err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
	ret = ERR_PTR(err);
	if (unlikely(err))
		goto out;

	err = au_di_init(dentry);
	ret = ERR_PTR(err);
	if (unlikely(err))
		goto out_si;

	inode = NULL;
	npositive = 0; /* suppress a warning */
	parent = dentry->d_parent; /* dir inode is locked */
	di_read_lock_parent(parent, AuLock_IR);
	err = au_alive_dir(parent);
	if (!err)
		err = au_digen_test(parent, au_sigen(sb));
	if (!err) {
		/* regardless LOOKUP_CREATE, always ALLOW_NEG */
		npositive = au_lkup_dentry(dentry, au_dbtop(parent),
					   AuLkup_ALLOW_NEG);
		err = npositive;
	}
	di_read_unlock(parent, AuLock_IR);
	ret = ERR_PTR(err);
	if (unlikely(err < 0))
		goto out_unlock;

	if (npositive) {
		inode = au_new_inode(dentry, /*must_new*/0);
		if (IS_ERR(inode)) {
			ret = (void *)inode;
			inode = NULL;
			goto out_unlock;
		}
	}

	if (inode)
		atomic_inc(&inode->i_count);
	ret = d_splice_alias(inode, dentry);
#if 0
	if (unlikely(d_need_lookup(dentry))) {
		spin_lock(&dentry->d_lock);
		dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
		spin_unlock(&dentry->d_lock);
	} else
#endif
	if (inode) {
		if (!IS_ERR(ret)) {
			iput(inode);
			if (ret && ret != dentry)
				ii_write_unlock(inode);
		} else {
			ii_write_unlock(inode);
			iput(inode);
			inode = NULL;
		}
	}

out_unlock:
	di_write_unlock(dentry);
out_si:
	si_read_unlock(sb);
out:
	return ret;
}
コード例 #19
0
ファイル: file.c プロジェクト: fullstory-morgue/aufs
int au_do_open(struct inode *inode, struct file *file,
	       int (*open)(struct file *file, int flags))
{
	int err, coo;
	struct dentry *dentry;
	struct super_block *sb;
	aufs_bindex_t bstart;
	struct inode *h_dir, *dir;

	dentry = file->f_dentry;
	LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));

	sb = dentry->d_sb;
	si_read_lock(sb);
	coo = 0;
#if 0
	switch (au_flag_test_coo(sb)) {
	case AuFlag_COO_LEAF:
		coo = !S_ISDIR(inode->i_mode);
		break;
	case AuFlag_COO_ALL:
		coo = 1;
		break;
	}
#endif
	err = au_init_finfo(file);
	//if (LktrCond) {fi_write_unlock(file); fin_finfo(file); err = -1;}
	if (unlikely(err))
		goto out;

	if (!coo) {
		di_read_lock_child(dentry, AUFS_I_RLOCK);
		bstart = dbstart(dentry);
	} else {
		di_write_lock_child(dentry);
		bstart = dbstart(dentry);
		if (test_ro(sb, bstart, dentry->d_inode)) {
			err = do_coo(dentry, bstart);
			if (err) {
				di_write_unlock(dentry);
				goto out_finfo;
			}
			bstart = dbstart(dentry);
		}
		di_downgrade_lock(dentry, AUFS_I_RLOCK);
	}

	// todo: remove this extra locks
	dir = dentry->d_parent->d_inode;
	if (!IS_ROOT(dentry))
		ii_read_lock_parent(dir);
	h_dir = au_h_iptr_i(dir, bstart);
	hdir_lock(h_dir, dir, bstart);
	err = open(file, file->f_flags);
	//if (LktrCond) err = -1;
	hdir_unlock(h_dir, dir, bstart);
	if (!IS_ROOT(dentry))
		ii_read_unlock(dir);
	di_read_unlock(dentry, AUFS_I_RLOCK);

 out_finfo:
	fi_write_unlock(file);
	if (unlikely(err))
		au_fin_finfo(file);
	//DbgFile(file);
 out:
	si_read_unlock(sb);
	TraceErr(err);
	return err;
}