struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
			   struct au_branch *br, struct nameidata *nd)
{
	struct dentry *h_dentry;
	int err;
	struct nameidata h_nd;

	if (au_test_fs_null_nd(h_parent->d_sb))
		return vfsub_lookup_one_len(name->name, h_parent, name->len);

	au_h_nd(&h_nd, nd);
	h_nd.path.dentry = h_parent;
	h_nd.path.mnt = br->br_mnt;

	err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
	h_dentry = ERR_PTR(err);
	if (!err) {
		path_get(&h_nd.path);
		h_dentry = vfsub_lookup_hash(&h_nd);
		path_put(&h_nd.path);
	}

	AuTraceErrPtr(h_dentry);
	return h_dentry;
}
static noinline_for_stack
int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
		    struct dentry *dentry, aufs_bindex_t bindex)
{
	int err, valid;
	int (*reval)(struct dentry *, struct nameidata *);

	err = 0;
	reval = NULL;
	if (h_dentry->d_op)
		reval = h_dentry->d_op->d_revalidate;
	if (!reval)
		goto out;

	AuDbg("b%d\n", bindex);
	if (au_test_fs_null_nd(h_dentry->d_sb))
		/* it may return tri-state */
		valid = reval(h_dentry, NULL);
	else {
		struct nameidata h_nd;
		int locked;
		struct dentry *parent;

		au_h_nd(&h_nd, nd);
		parent = nd->path.dentry;
		locked = (nd && nd->path.dentry != dentry);
		if (locked)
			di_read_lock_parent(parent, AuLock_IR);
		BUG_ON(bindex > au_dbend(parent));
		h_nd.path.dentry = au_h_dptr(parent, bindex);
		BUG_ON(!h_nd.path.dentry);
		h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
		path_get(&h_nd.path);
		valid = reval(h_dentry, &h_nd);
		path_put(&h_nd.path);
		if (locked)
			di_read_unlock(parent, AuLock_IR);
	}

	if (unlikely(valid < 0))
		err = valid;
	else if (!valid)
		err = -EINVAL;

out:
	AuTraceErr(err);
	return err;
}
Beispiel #3
0
int vfsub_create(struct inode *dir, struct path *path, int mode)
{
	int err;
	struct dentry *d;

	IMustLock(dir);

	d = path->dentry;
	path->dentry = d->d_parent;
	err = security_path_mknod(path, d, mode, 0);
	path->dentry = d;
	if (unlikely(err))
		goto out;

	if (au_test_fs_null_nd(dir->i_sb))
		err = vfs_create(dir, path->dentry, mode, NULL);
	else {
		struct nameidata h_nd;

		memset(&h_nd, 0, sizeof(h_nd));
		h_nd.flags = LOOKUP_CREATE;
		h_nd.intent.open.flags = O_CREAT
			| vfsub_fmode_to_uint(FMODE_READ);
		h_nd.intent.open.create_mode = mode;
		h_nd.path.dentry = path->dentry->d_parent;
		h_nd.path.mnt = path->mnt;
		path_get(&h_nd.path);
		err = vfs_create(dir, path->dentry, mode, &h_nd);
		path_put(&h_nd.path);
	}

	if (!err) {
		struct path tmp = *path;
		int did;

		vfsub_update_h_iattr(&tmp, &did);
		if (did) {
			tmp.dentry = path->dentry->d_parent;
			vfsub_update_h_iattr(&tmp, /*did*/NULL);
		}
		/*ignore*/
	}

out:
	return err;
}