Exemple #1
0
static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
			      struct au_branch *br)
{
	int err;
	struct au_iattr ia;
	struct inode *h_inode;
	struct dentry *h_d;
	struct super_block *h_sb;

	err = 0;
	memset(&ia, -1, sizeof(ia));
	h_sb = h_dentry->d_sb;
	h_inode = NULL;
	if (d_is_positive(h_dentry)) {
		h_inode = d_inode(h_dentry);
		au_iattr_save(&ia, h_inode);
	} else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
		/* nfs d_revalidate may return 0 for negative dentry */
		/* fuse d_revalidate always return 0 for negative dentry */
		goto out;

	/* main purpose is namei.c:cached_lookup() and d_revalidate */
	h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent);
	err = PTR_ERR(h_d);
	if (IS_ERR(h_d))
		goto out;

	err = 0;
	if (unlikely(h_d != h_dentry
		     || d_inode(h_d) != h_inode
		     || (h_inode && au_iattr_test(&ia, h_inode))))
		err = au_busy_or_stale();
	dput(h_d);

out:
	AuTraceErr(err);
	return err;
}
Exemple #2
0
/*
 * simple tests for the adding inode operations.
 * following the checks in vfs, plus the parent-child relationship.
 */
int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
	       struct dentry *h_parent, int isdir, struct au_ndx *ndx)
{
	int err, exist;
	struct dentry *h_dentry;
	struct inode *h_inode;
	umode_t h_mode;

	LKTRTrace("%.*s/%.*s, b%d, dir %d\n",
		  AuDLNPair(h_parent), AuDLNPair(dentry), bindex, isdir);

	exist = !!dentry->d_inode;
	h_dentry = au_h_dptr(dentry, bindex);
	h_inode = h_dentry->d_inode;
	if (!exist) {
		err = -EEXIST;
		if (unlikely(h_inode))
			goto out;
	} else {
		/* rename(2) case */
		err = -EIO;
		if (unlikely(!h_inode || !h_inode->i_nlink))
			goto out;

		h_mode = h_inode->i_mode;
		if (!isdir) {
			err = -EISDIR;
			if (unlikely(S_ISDIR(h_mode)))
				goto out;
		} else if (unlikely(!S_ISDIR(h_mode))) {
			err = -ENOTDIR;
			goto out;
		}
	}

	err = -EIO;
	/* expected parent dir is locked */
	if (unlikely(h_parent != h_dentry->d_parent))
		goto out;
	err = 0;

	if (au_opt_test(au_mntflags(dentry->d_sb), UDBA_INOTIFY)) {
		struct dentry *h_latest;
		struct qstr *qstr = &dentry->d_name;

		err = -EACCES;
		if (unlikely(au_test_h_perm
			     (h_parent->d_inode, MAY_EXEC | MAY_WRITE,
			      au_ftest_ndx(ndx->flags, DLGT))))
			goto out;

		h_latest = au_sio_lkup_one(qstr->name, h_parent, qstr->len,
					   ndx);
		err = PTR_ERR(h_latest);
		if (IS_ERR(h_latest))
			goto out;
		err = -EIO;
		dput(h_latest);
		/* fuse d_revalidate always return 0 for negative dentries */
		if (h_latest == h_dentry || au_test_fuse(h_dentry->d_sb))
			err = 0;
	}

 out:
	AuTraceErr(err);
	return err;
}