예제 #1
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;
}
예제 #2
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;
}
예제 #3
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;
}
예제 #4
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;
}